【问题标题】:MongoDB - can not get a covered queryMongoDB - 无法获得涵盖的查询
【发布时间】:2014-05-21 07:13:33
【问题描述】:

所以我有一个空数据库“tests”和一个名为“test”的集合。 首先,我确保我的索引设置正确。

db.test.ensureIndex({t:1})
db.test.getIndices()

[

    {
        "v" : 1,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "tests.test"
    },
    {
        "v" : 1,
        "key" : {
            "t" : 1
        },
        "name" : "t_1",
        "ns" : "tests.test"
    }
]

之后我插入了一些测试记录。

db.test.insert({t:1234})
db.test.insert({t:5678})

当我使用以下命令查询数据库并让 Mongo 解释结果时,我得到以下输出:

db.test.find({t:1234},{_id:0}).explain()

{

    "cursor" : "BtreeCursor t_1",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,
    "nscannedObjectsAllPlans" : 1,
    "nscannedAllPlans" : 1,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
        "t" : [
            [
                1234,
                1234
            ]
        ]
    },
    "server" : "XXXXXX:27017",
    "filterSet" : false
}

谁能解释一下为什么 indexOnly 是假的?

提前致谢。

【问题讨论】:

    标签: mongodb indexing


    【解决方案1】:

    要成为covered index query,您只需检索索引中的那些字段:

    > db.test.find({ t: 1234 },{ _id: 0, t: 1}).explain()
    {
        "cursor" : "BtreeCursor t_1",
        "isMultiKey" : false,
        "n" : 1,
        "nscannedObjects" : 0,
        "nscanned" : 1,
        "nscannedObjectsAllPlans" : 0,
        "nscannedAllPlans" : 1,
        "scanAndOrder" : false,
        "indexOnly" : true,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 0,
        "indexBounds" : {
                "t" : [
                        [
                                1234,
                                1234
                        ]
                ]
        },
        "server" : "ubuntu:27017",
        "filterSet" : false
    }
    

    基本上这意味着使用索引来检索数据,而无需返回实际文档并检索更多信息。这可以是您需要的任意数量的字段(在 reason 范围内),但它们确实需要包含在索引中并且是唯一返回的字段。

    【讨论】:

    • 谢谢。我认为在返回值的投影中我不必特别说 {t:1},因为在没有启用 t 的情况下,我只从上面的查询中返回了 't',
    • @aQuip 这里要做的主要事情是删除不会包含在索引中的_id 字段。
    • 我不是用这个查询db.test.find({t:1234},{_id:0}).explain()做的吗?
    • @aQuip 从技术上讲,这意味着所有其他字段,但不包括 _id。因此,即使唯一的其他字段是t,优化器实际上并不知道这一点,并假定它没有被覆盖或“indexOnly”,因为您没有明确命名索引中包含的所有字段。
    • @NeilOkay 我想我明白了。感谢您的快速帮助。
    【解决方案2】:

    嗯,原因还没有解释清楚(实际上让我很困惑)所以这是我的努力。

    基本上为了让 MongoDB 知道所述索引涵盖了查询,它必须知道您想要哪些字段。

    如果你只是说你不想要_id,它怎么不看就知道* - _id = t

    这里* 代表所有字段,就像在 SQL 中一样。

    答案是不能。这就是为什么您需要提供完整的字段/选择/投影/他们用于定义的任何词,以便 MongoDB 可以知道您的返回符合索引。

    【讨论】:

    • 当然“答案是不能。”以及一堆无用的言辞。你没有回答问题。这只不过是一个扩展评论。有一个答案。你说不清楚?然而实际上提供了一个工作示例,并且还花时间向不了解该问题的新用户进一步解释。面对这一切,你不得不说的是。 “为什么投反对票?”。既然你不能支持“正确和有帮助”,我就告诉你为什么人们会投反对票。
    • @NeilLunn 我说,作为对上述两段陈述的回应,当作为一个组阅读时确实提供了答案,MongoDB 无法知道{_id:0}{_id:0,t:1}(因为t 是文档中唯一的字段)是相同的,而不像您自己的答案所证明的那样。这可能是一个扩展评论,但在我看来,您的回答还不足以真正说明这一点。您的回答说明了一个解决方案,但似乎它实际上并没有说明 为什么 它正在发生。如果我的回答中有错误信息,请随时告诉我。
    • @NeilLunn 问题也不应该是“谁能向我解释为什么 indexOnly 是错误的?”这似乎我的回答确实有帮助
    • 你没有解释。我解释了,我也解释了你的问题。
    • @NeilLunn 您解释了需要将字段放入投影中,但您没有确切说明为什么 MongoDB 无法知道 {_id:0}{_id:0,t:1}[_id,t] 的文档中是相同的,使用正如我现在所看到的,只有一个索引,直到您解释它时对您的答案的第 4 条评论才出现,并且 OP 理解为什么并在表示感谢后标记您的答案。直到你说出我在上面所做的事情的简要版本,OP 才满意。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 2014-09-17
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多