Mongodb查询异常缓慢

时间:2014-03-25 13:23:11

标签: mongodb

我的mongodb相当简单:数据集/条目在3层上有大约30个属性。一个这样的条目最多约5000个字符。我有500k他们。 当我执行以下查询...

db.images.find({ "featureData.cedd": { $exists: false}}).count()

......非常慢。它没有编入索引,但仍然......根据我的MySQL经验,它不应该 20分钟来执行一个这样的查询。

执行时(直接在mongo终端上)有3%的CPU使用率和超过2 Gig的可用内存。

感谢您给我一些关于我能做什么的提示!

编辑:查询的解释()(不计数)给出:

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" : {

    }
}

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

添加索引后解释()的输出

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
                    ]
            ]
    }
}

2 个答案:

答案 0 :(得分:6)

TL; DR:反转逻辑:在新字段has_cedd上添加稀疏索引,该字段为空或某些常量(低选择性索引,不理想,但通过稀疏改进),或者更好,保持其他地方的全局计数器,在每次写操作时都会更新。

索引featureData.cedd如果它可以包含多达5k个字符听起来是一个坏主意,因为这远远超出了最大索引大小,显然你对数据本身不感兴趣,只是它&#是否#&# 39;礼物。

哦,为什么这么慢?可能会快速保持临时请求。 MongoDB可以将所有资源专用于这种类似OLAP的查询,但这会在任何常规的OLTP样式查询中引入延迟。


这里有两个问题:

  1. $exists : false是邪恶的,我怀疑索引会有所帮助:索引是针对数据,而$exists是一个'元查询&# 39;在结构上。如果字段中有一个索引是$exists : true,它可以使用索引,因为如果存在索引值,则字段本身也必须存在于给定文档中。颠倒这种逻辑很棘手:如果该字段不存在,则它不在索引中或者具有超低选择性。 '转身'索引通常是有问题的,顺便说一句,使用$ne的查询也是如此。

  2. MongoDB必须反序列化500k对象并检查每个对象以执行$exists。您不能将此与具有固定表结构的MySQL进行比较,事实上,$exists : false没有SQL等价物,因为该字段必须存在,否则您的表会严重破坏。

答案 1 :(得分:0)

在我的案例中,添加索引可将查询速度提高600倍。 $exists:false会查找空值 - 只有在其他对象经常不具有cedd:null(作为有效值)时才会有效。这就是这种情况。此外,没有cedd值的对象要小得多。