【问题标题】:How does Indexing a field affect the sorting order of docs without the indexed field in MongoDB?索引字段如何影响 MongoDB 中没有索引字段的文档的排序顺序?
【发布时间】:2019-01-03 12:04:36
【问题描述】:

我有一个集合students,文档很少

[{id:1, name:'AA'}, {id:2, name:'BB'}]

我正在获取按文档中不存在的字段排序的文档

db.students.find().sort({marks: -1})

它按这个顺序给我文档

[{id:1, name:'AA'}, {id:2, name:'BB'}]

现在当我添加索引时

db.students.createIndex({'marks':1})

然后调用相同的查询

db.students.find().sort({marks: -1})

顺序变了!!

[{id:2, name:'BB'},{id:1, name:'AA'}]

索引字段如何影响缺少该字段的文档的排序顺序?

注意:这可能不是一个有效的示例。但我的问题是类似的。

【问题讨论】:

    标签: mongodb indexing


    【解决方案1】:

    Mongodb 将在两个不同的时间执行排序。

    1. 查询时间(该字段没有索引)
    2. 索引时间。 (当我们创建索引时) 因此,对于相同的查询,您会得到不同的结果。

    无索引:

    当我们在 mongodb 中执行排序(排序字段上没有索引)时,将在查询时通过扫描整个集合开始对集合进行排序。

    排序的方向将是向前的(偶数标记:-1),即它将首先接触文档的插入顺序(_id 值)。

    当遇到两个具有相同字段的文档(标记:两个文档为空)时,它会按照它们的_id值排列它们。

    带索引:

    您按升序在标记字段上创建了索引(索引只不过是生成以键为标记的 B-tree)。

    当我们尝试使用marks:1 对集合进行排序时,我们将按索引顺序获得相同的结果。

    当我们尝试使用标记对集合进行排序时:-1 然后 mongodb 将开始从向后返回文档,因为文档已经按升序索引(排序)。

    这就是我们得到不同结果的原因。

    当您对它们执行explain() 时,您可以获得有关这些查询的更多详细信息。

    无索引:

    db.students2.find().sort({marks:-1}).explain()
    {
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "stackoverflow.students2",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ ]
        },
        "winningPlan" : {
            "stage" : "SORT",
            "sortPattern" : {
                "marks" : -1
            },
            "inputStage" : {
                "stage" : "SORT_KEY_GENERATOR",
                "inputStage" : {
                    "stage" : "COLLSCAN",
                    "filter" : {
                        "$and" : [ ]
                    },
                    "direction" : "forward"
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "sys2030",
        "port" : 27017,
        "version" : "3.2.22",
        "gitVersion" : "105adca0d443f9a1a5abd608fd7133840a68dd"
    },
    "ok" : 1
    }
    

    我们没有索引,所以 mongodb 在查询时开始扫描它。

    带索引:

    db.students.find().sort({marks:-1}).explain()
    {
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "stackoverflow.students",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ ]
        },
        "winningPlan" : {
            "stage" : "FETCH",
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "marks" : 1
                },
                "indexName" : "marks_1",
                "isMultiKey" : false,
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 1,
                "direction" : "backward",
                "indexBounds" : {
                    "marks" : [
                        "[MaxKey, MinKey]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ ]
    },
    "serverInfo" : {
        "host" : "sys2030",
        "port" : 27017,
        "version" : "3.2.22",
        "gitVersion" : "105adca0d443f9a1a5abd608fd7133840a68dd"
    },
    "ok" : 1
    }
    

    我们有 index ,所以 mongodb 开始使用它并简单地从 backs(marks:-1) 返回结果。

    这就是我们在collection很大的时候进行排序的原因,monogodb会报错:sort with large amount of data , without index。

    进一步阅读

    https://docs.mongodb.com/manual/tutorial/sort-results-with-indexes/

    https://docs.mlab.com/indexing/

    【讨论】:

      猜你喜欢
      • 2011-08-28
      • 1970-01-01
      • 2017-02-01
      • 1970-01-01
      • 2013-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-19
      相关资源
      最近更新 更多