Mongodb查询异常缓慢
我的mongodb相当简单:一个数据集/条目在3层上有大约30个属性。其中一个条目最多可包含5000个字符。我有50万个。 当我执行以下查询时Mongodb查询异常缓慢,mongodb,Mongodb,我的mongodb相当简单:一个数据集/条目在3层上有大约30个属性。其中一个条目最多可包含5000个字符。我有50万个。 当我执行以下查询时 db.images.find({ "featureData.cedd": { $exists: false}}).count() …速度非常慢。它没有索引,但仍然。。根据我的MySQL经验,执行这样一个查询不应该花费20分钟 在执行时(直接在mongo终端上),CPU使用率为3%,可用内存仍超过2 Gig 谢谢你给我一个关于我能做什么的提示 编辑:查询
db.images.find({ "featureData.cedd": { $exists: false}}).count()
…速度非常慢。它没有索引,但仍然。。根据我的MySQL经验,执行这样一个查询不应该花费20分钟
在执行时(直接在mongo终端上),CPU使用率为3%,可用内存仍超过2 Gig
谢谢你给我一个关于我能做什么的提示
编辑:查询(不含计数)的explain()给出:
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
添加索引后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
]
]
}
}
TL;DR:颠倒逻辑:在一个新字段上添加一个稀疏索引
has_cedd
,该字段要么为空,要么为常数(低选择性索引,不理想,但通过稀疏改进),或者更好的是,在其他地方保留一个全局计数器,在每次写入操作时更新
索引featureData.cedd
如果它最多可以包含5k个字符,听起来是个坏主意,因为这远远超过了最大索引大小,而且显然您对数据本身不感兴趣,只关心它是否存在
哦,为什么这么慢?可能是为了让临时请求保持快速。MongoDB可以将所有资源专用于这种类似OLAP的查询,但这会给任何“常规OLTP样式的查询”带来延迟
这里有两个问题:
$exists:false
是邪恶的,我怀疑索引是否有用:索引是为数据创建的,而$exists
是结构上的“元查询”。如果字段上有索引且查询为$exists:true
,则可以使用索引,因为如果存在索引值,则字段本身也必须存在于给定文档上。逆转这种逻辑很棘手:如果字段不存在,它就不在索引中,或者它的选择性极低扭转“索引”通常是有问题的,顺便说一下,对于使用$ne
的查询也是如此$exists
。您无法将其与MySQL进行比较,MySQL具有固定的表结构,事实上,$exists:false
没有SQL等价物,因为该字段必须存在,否则您的表将严重损坏在我的例子中,添加索引将查询速度提高了60万倍
$exists:false
查找空值-这仅在其他对象不经常具有cedd:null
的情况下有效(作为有效值)。这里就是这样。此外,没有SEDD值的对象要小得多。 <代码>解释< /代码> ING。查询总是一个很好的第一步,请在编写诸如“计数mongo必须通过所有tupes”这样的东西之前考虑一下,我们在这里只讨论了15分钟,只记录了一百万个记录。我只能找到一个“explain()”,没有描述。“explain”运行了1分钟,但x/同样的低CPU和内存usageexplain()尚未终止。一旦磁盘IO受到限制,我就在这里写。iostat怎么说?谢谢你的解释!我仍然想知道为什么OLAP查询只使用3%的CPU?我能增加这个吗?由于数据库上没有运行其他任何东西,这将是对资源的浪费…五月天添加索引将其从20分钟增加到2毫秒!世界跆拳道联盟!我在问题中添加了新的explain()作为编辑,所以我猜索引创建了一个单独的列表,其中没有这样的索引功能,因此搜索只需扫描确切数量的结果,在这种情况下是438?啊,很有趣$exists:false
查找空值-这仅在其他对象不经常具有cedd:null
的情况下有效(作为有效值),但情况似乎就是这样。这些对象可能要小得多,因为cedd
字段太大了,对吗?否则,查询速度应“仅”快千倍。您使用什么数据类型作为主键?int。但在本例中,我不按id查询,只是说。但是,是的,没有cedd功能的设备往往要小得多。我也对这个因素感到惊讶,它提高了60万倍^^
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
]
]
}
}