我的mongodb相当简单:数据集/条目在3层上有大约30个属性.一个这样的条目最多约5000个字符.我有500k他们.当我执行以下查询时...
db.images.find({ "featureData.cedd": { $exists: false}}).count()
Run Code Online (Sandbox Code Playgroud)
......它非常慢.它没有索引,但仍然......从我的MySQL经验来看,执行一个这样的查询不应该花20分钟.
在执行时(直接在mongo终端上)有3%的CPU使用率和超过2 Gigs的可用内存.
谢谢你给我一个关于我能做什么的暗示!
编辑:查询的解释()(不计数)给出:
db.images.find({ "featureData.cedd": { $exists: false }}).explain()
{
"cursor" : "BasicCursor",
"nscanned" : 532537,
"nscannedObjects" : 532537,
"n" : 438,
"millis" : 1170403,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {
}
}
Run Code Online (Sandbox Code Playgroud)
iostat的输出:
Linux 3.2.0-58-generic (campartex) 03/25/2014 _x86_64_ (2 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
34.93 0.01 0.25 0.48 0.00 64.33
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 2.08 103.79 11.26 172805914 18749067
fd0 0.00 0.00 0.00 148 0
Run Code Online (Sandbox Code Playgroud)
添加索引后输出explain():
db.images.find({ "featureData.cedd": { $exists: false }}).explain()
{
"cursor" : "BtreeCursor featureData.cedd_1",
"nscanned" : 438,
"nscannedObjects" : 438,
"n" : 438,
"millis" : 2,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : true,
"indexOnly" : false,
"indexBounds" : {
"featureData.cedd" : [
[
null,
null
]
]
}
}
Run Code Online (Sandbox Code Playgroud)
TL; DR:反转逻辑:在新字段上添加稀疏索引,该字段has_cedd为空或某些常量(低选择性索引,不理想,但通过稀疏改进),或者更好的是,在更新的其他地方保留一个全局计数器在每次写操作.
如果索引featureData.cedd可以包含多达5k个字符,那么索引听起来就像一个坏主意,因为它远远超出了最大索引大小,显然你对数据本身不感兴趣,只是它是否存在.
哦,为什么这么慢?可能会快速保持临时请求.MongoDB可以将所有资源专用于这种类似OLAP的查询,但这会在任何"常规OLTP样式查询"上引入延迟.
这里有两个问题:
$exists : false是邪恶的,我怀疑索引将有所帮助:索引是为数据做的,而$exists对结构是一个'元查询'.如果字段上有一个索引,则可以使用索引$exists : true,因为如果存在索引值,则字段本身也必须存在于给定文档中.颠倒这种逻辑很棘手:如果该字段不存在,则它不在索引中或者具有超低选择性."扭转"索引通常是有问题的,$ne顺便说一下,查询也是如此.
MongoDB必须反序列化500k对象并检查每个对象以执行$exists.您无法将此与具有固定表结构的MySQL进行比较,实际上,$exists : false它没有SQL等效项,因为该字段必须存在,否则您的表会严重损坏.
| 归档时间: |
|
| 查看次数: |
1530 次 |
| 最近记录: |