首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么查询扫描它找到的文档的8倍- MongoDB

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

Stack Overflow用户
提问于 2015-06-15 10:55:56
回答 1查看 47关注 0票数 2

我有50份文件(供审判之用),大致类似于这一份:

代码语言:javascript
复制
  "_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
        }
    ]
}

我做了以下索引:

代码语言:javascript
复制
{
    "f.t" : 1,
    "f.v" : 1
}

因此,我提出以下查询:

代码语言:javascript
复制
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()

解释文件:

代码语言:javascript
复制
{
    "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份),而只有6份是匹配的文件。为什么扫描/匹配的文档比率如此之低(是吗?)有什么更好的方法来改进它吗?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-06-15 11:49:54

它不是所谓的“文档”--而是“对象”,但您不会是第一个不完全理解.explain()输出的人。

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

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

代码语言:javascript
复制
{ "f.t": "ry", "f.v": 1972 },
{ "f.t": "g",  "f.v": "Crime" },
{ "f.t": "g",  "f.v": "Drama" }

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

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

这本质上是“对象”和“文档”与查询计划器作为输出所提供的内容之间的区别。

注意:"Geospatial“类型的查询也有类似的情况,其基础是引擎如何实际存储事物,以及在与查询交互时如何检索这些查询,并在这里解释报告超出预期文档计数的”类似“文档扩展的输出。但所有这些都只是索引中的“对象”,而这些索引都是这样处理的。

所以:

  • n是“结果”文档
  • nScannedObjects是对象
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30843408

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档