为什么查询扫描它找到的文件的8倍 - MongoDB

时间:2015-06-15 10:55:56

标签: mongodb

我有50个文件(用于试用)或多或少像这样:

  "_id" : ObjectId("5461c8f0426f727f16010000"),
    "f" : [ 
        {
            "t" : "ry",
            "v" : 1972
        }, 
        {
            "t" : "g",
            "v" : [ 
                "Crime", 
                "Drama"
            ]
        }, 
        {
            "t" : "ml",
            "v" : "English"
        }, 
        {
            "t" : "k",
            "v" : "movie"
        }, 
        {
            "t" : "ai",
            "v" : 972353
        }, 
        {
            "t" : "ec",
            "v" : 46
        }, 
        {
            "t" : "rel",
            "v" : true
        }
    ]
}

我做了以下索引:

{
    "f.t" : 1,
    "f.v" : 1
}

所以我做了以下查询:

db.items.find( 
    {
        "$and": [
            {"f": {$elemMatch: {"t": "ry", "v": {$gt: 1980, $lt: 2000}}}},
            {"f": {$elemMatch: {"t": "g", "v": {$in: ["Drama"]}}}},
                        {"f": {$elemMatch: {"t": "k", "v": "movie"}}}
        ]
    }

).explain()

解释文件:

{
    "cursor" : "BtreeCursor f.t_1_f.v_1",
    "isMultiKey" : true,
    "n" : 6,
    "nscannedObjects" : 50,
    "nscanned" : 50,
    "nscannedObjectsAllPlans" : 50,
    "nscannedAllPlans" : 50,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "f.t" : [ 
            [ 
                "k", 
                "k"
            ]
        ],
        "f.v" : [ 
            [ 
                "movie", 
                "movie"
            ]
        ]
    },
    "server" : "b009115.mongolab.com:42700",
    "filterSet" : false,
    "stats" : {
        "type" : "KEEP_MUTATIONS",
        "works" : 51,
        "yields" : 0,
        "unyields" : 0,
        "invalidates" : 0,
        "advanced" : 6,
        "needTime" : 44,
        "needFetch" : 0,
        "isEOF" : 1,
        "children" : [ 
            {
                "type" : "FETCH",
                "works" : 51,
                "yields" : 0,
                "unyields" : 0,
                "invalidates" : 0,
                "advanced" : 6,
                "needTime" : 44,
                "needFetch" : 0,
                "isEOF" : 1,
                "alreadyHasObj" : 0,
                "forcedFetches" : 0,
                "matchTested" : 6,
                "children" : [ 
                    {
                        "type" : "IXSCAN",
                        "works" : 51,
                        "yields" : 0,
                        "unyields" : 0,
                        "invalidates" : 0,
                        "advanced" : 50,
                        "needTime" : 0,
                        "needFetch" : 0,
                        "isEOF" : 1,
                        "keyPattern" : "{ f.t: 1.0, f.v: 1.0 }",
                        "isMultiKey" : 1,
                        "boundsVerbose" : "field #0['f.t']: [\"k\", \"k\"], field #1['f.v']: [\"movie\", \"movie\"]",
                        "yieldMovedCursor" : 0,
                        "dupsTested" : 50,
                        "dupsDropped" : 0,
                        "seenInvalidated" : 0,
                        "matchTested" : 0,
                        "keysExamined" : 50,
                        "children" : []
                    }
                ]
            }
        ]
    }
}

如我所见,当只有六个是匹配的文件时,它扫描了所有文件(50)。为什么扫描/匹配的文档比例太差(是吗?)。有没有更好的方法来改善它?

谢谢!

1 个答案:

答案 0 :(得分:1)

这不是“文件”它是“对象”,但你不会是第一个不完全理解.explain()输出的人。

简单地说,作为索引的一部分,你有一个“数组”元素(实际上允许的最大“两个”),这意味着你的索引就是我们所说的“MultiKey”。这意味着,在非常基本的术语中,“复合”索引具有在其中指定的值的“每种可能的组合”。

索引数据的“非常基本”视图可能如下所示:

{ "f.t": "ry", "f.v": 1972 },
{ "f.t": "g",  "f.v": "Crime" },
{ "f.t": "g",  "f.v": "Drama" }

简而言之,这是“三”(3)条目,对应于集合中将在集合中扫描的“单个文档”。

当然,考虑到您的查询条件,“过滤掉”。因此,在这里寻找"f.t": "g"意味着“两个”(2)对象被扫描。

这实质上是“对象”和“文档”之间的区别,与查询计划程序提供的输出有关。

注意:“地理空间”类型查询的类似情况基于引擎实际存储的内容以及在与查询交互时如何检索它们并在此处解释输出报告超出预期文档的“类似”“文档扩展”计数。但它只是索引中的“对象”,正在以这种方式对待。

所以:

  • n是“结果”文件
  • nScannedObjects是对象