为什么在这里扫描任何物体?

时间:2012-03-19 19:13:13

标签: mongodb

我有一个索引:

{indices.textLc:1, group:1, lc:1, wordCount:1, pattern:1, clExists:1} 

和Morphia生成如下查询:

{
    $and: [{
        lc: "eng"
    },
    {
        $or: [{
            group: "cn"
        },
        {
            group: "all"
        }]
    },
    {
        "indices.textLc": {
            $in: ["media strengthening", "strengthening", "media"]
        }
    },
    {
        wordCount: {
            $gte: 1
        }
    },
    {
        wordCount: {
            $lte: 2
        }
    }]
}

并解释给出:

{
    "cursor" : "BtreeCursor indices.textLc_1_group_1_lc_1_wordCount_1_pattern_1_clExists_1 multi",
    "nscanned" : 20287,
    "nscannedObjects" : 20272,
    "n" : 22,
    "millis" : 677,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "isMultiKey" : true,
    "indexOnly" : false,
    "indexBounds" : {
        "indices.textLc" : [
            [
                "media",
                "media"
            ],
            [
                "media strengthening",
                "media strengthening"
            ],
            [
                "strengthening",
                "strengthening"
            ]
        ],
        "group" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ],
        "lc" : [
            [
                "eng",
                "eng"
            ]
        ],
        "wordCount" : [
            [
                1,
                1.7976931348623157e+308
            ]
        ],
        "pattern" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ],
        "clExists" : [
            [
                {
                    "$minElement" : 1
                },
                {
                    "$maxElement" : 1
                }
            ]
        ]
    }

首先,我不明白为什么需要扫描,因为索引中的所有内容都可用。更具体地说,为什么indexBounds的wordCount部分看起来不像:

 "wordCount" : [
            [
                1,
                2
            ]
        ],

更新2012-03-20 :如果它有助于解释任何事情,我正在运行MongoDB 2.0.3

1 个答案:

答案 0 :(得分:1)

查询中的每个字段在复合索引中都可用,但很少说明它是否可以将一个索引用于查询中的每个子句。有几点需要考虑:

  • 除了可以使用索引每个子句的顶级$或子句之外,每个MongoDB查询最多只能使用一个索引。
  • 复合索引仅在复合中的每个后续字段可以按顺序使用时起作用,这意味着您的查询允许首先对第一个索引字段进行过滤,然后对第二个索引字段进行过滤,依此类推。因此,如果您有索引{a:1,b:1},查询{b:“嗨!”}将不会使用索引,即使该字段位于复合索引中。

现在,您的查询需要扫描的原因是因为您的索引只能优化“indices.textLc”字段(您的第一个索引字段)的查询执行计划,并且在此特定情况下为“lc”,因为它是一个单独的子句在你的$和。

解释的“wordCount”部分实际上应该是:

 "wordCount" : [
         [
                 1,
                 2
         ]
 ]

我刚测试了它,它在我的机器上测试了,所以我认为你的Morphia /制图解决方案出了问题。

复合索引和诸如你的复杂查询是一个棘手的主题。我现在没时间查看您的查询和索引,看看它是否可以优化。如果可以的话,今晚我会再次访问并帮助你。