Mongodb查询异常缓慢

Mongodb查询异常缓慢,mongodb,Mongodb,我的mongodb相当简单:一个数据集/条目在3层上有大约30个属性。其中一个条目最多可包含5000个字符。我有50万个。 当我执行以下查询时 db.images.find({ "featureData.cedd": { $exists: false}}).count() …速度非常慢。它没有索引,但仍然。。根据我的MySQL经验,执行这样一个查询不应该花费20分钟 在执行时(直接在mongo终端上),CPU使用率为3%,可用内存仍超过2 Gig 谢谢你给我一个关于我能做什么的提示 编辑:查询

我的mongodb相当简单:一个数据集/条目在3层上有大约30个属性。其中一个条目最多可包含5000个字符。我有50万个。 当我执行以下查询时

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
    的查询也是如此

  • MongoDB必须对500k对象进行反序列化,并检查每个对象以执行
    $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
                        ]
                ]
        }
    }