【问题标题】:Why aren't my indexes only being used in this Mongo Query?为什么我的索引不只在这个 Mongo 查询中使用?
【发布时间】:2011-11-18 12:01:39
【问题描述】:

我在 Mongo 中有一个我认为非常简单、直接的查询,并创建了索引:

{ "Ended" : 1, "EndDate" -1 }

但是,当我对其运行一个简单的查询时,它似乎可以识别索引,但它仍在扫描大量对象以检索数据。这是我的查询和解释结果:

PRIMARY> db.listing.find({ "Ended" : { "$ne" : true }, "EndDate" : { "$lte" : ISODate("2011-11-18T00:47:40.638Z") } }).explain();
{
        "cursor" : "BtreeCursor Ended_1_EndDate_-1 multi",
        "nscanned" : 24508585,
        "nscannedObjects" : 24508583,
        "n" : 24508583,
        "millis" : 108323,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "isMultiKey" : false,
        "indexOnly" : false,
        "indexBounds" : {
                "Ended" : [
                        [
                                {
                                        "$minElement" : 1
                                },
                                true
                        ],
                        [
                                true,
                                {
                                        "$maxElement" : 1
                                }
                        ]
                ],
                "EndDate" : [
                        [
                                ISODate("2011-11-18T00:47:40.638Z"),
                                true
                        ]
                ]
        }
}

任何明显的想法我做错了什么?谢谢!

【问题讨论】:

  • 如果将"Ended" : { "$ne" : true } 替换为"Ended" : false 会发生什么? (或者这在您的架构中不起作用?)

标签: mongodb indexing mongodb-.net-driver


【解决方案1】:

索引对于 $ne 或 $nin 查询不是很好。你会更好

db.listing.find({ "Ended" : false , "EndDate" : { "$lte" : ISODate("2011-11-18T00:47:40.638Z") } })

这里的区别在于,如果没有“Ended”字段,或者“Ended”字段为空或其他类型,您将不再获取文档。

Indexing Advice & FAQ - MongDOB

【讨论】:

    【解决方案2】:

    n 字段表示您的查询匹配 24.5M 文档,与 nscannedObjects 相同的数量,这是正常行为。如果您不需要所有 24.5M 匹配文档,则应在查询中添加其他条件。

    我还看到您正在使用EndedDate: {$ne: true}。虽然这会起作用,但它会比EndedDate: false 慢,所以如果该字段可能只有truefalse,你最好选择后者。

    【讨论】:

    • 在这一点上我不能确定 end 存在。也许我应该运行一次查询以将此字段添加到旧文档中
    • 是的,你应该这样做。 $ne 操作是邪恶的,因为它暗示了一个不能被索引的$exists
    • $ne 暗示$exists 是什么意思?
    • 没关系,我期待您可以使用$ne null 查询来实现$exists,但这是无稽之谈。尽管如此,我认为我们同意$ne 是邪恶的,并且很可能是这里表现不佳的原因。
    • 有一些有用的案例。当然,它的性能不如精确匹配查找,但我不会称之为邪恶。
    【解决方案3】:

    它不会仅使用索引,因为您将通过该查询检索未编入索引的其他字段。

    您的所有文档过去是否都有 EndDate?当您使用当前日期的 LTE 时,它仍会扫描当前日期之前的所有索引项。它只扫描索引,比扫描整个文档更快。

    如果您查询日期范围,您会看到扫描对象的数量减少。

    【讨论】:

    • 大部分都在过去。有些是在未来。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多