MongoDB Index交叉示例?

问题描述 投票:0回答:1

我试图理解为什么MongoDB无法使用here中提到的Index交集。

我使用下面的代码块在intersection集合中插入了10000个文档:

for (var i = 0; i < 10; i++) {
    for (var j = 0; j < 10; j++) {
        for (var k = 0; k < 10; k++) {
            for (var l = 0; l < 10; l++) {
              db.intersection.insert({a:i, b:j, c:k, d:l});
            }
        }
    }
}

然后创建了这3个索引: db.intersection.createIndex({ a }) db.intersection.createIndex({ b : 1, c : 1 }) db.intersection.createIndex({ d : 1 })

在这一点上,我期待db.intersection.find({a:1,b:2,d:4})使用3个索引之间的交集,即。 a_1, b_1_c_1, d_1

然而情况并非如此,我可以看到获胜计划只使用一个索引,d_1

"winningPlan" : {
                        "stage" : "FETCH",
                        "filter" : {
                                "$and" : [
                                        {
                                                "a" : {
                                                        "$eq" : 1
                                                }
                                        },
                                        {
                                                "b" : {
                                                        "$eq" : 2
                                                }
                                        }
                                ]
                        },
                        "inputStage" : {
                                "stage" : "IXSCAN",
                                "keyPattern" : {
                                        "d" : 1
                                },
                                "indexName" : "d_1",
                                "isMultiKey" : false,
                                "multiKeyPaths" : {
                                        "d" : [ ]
                                },
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 2,
                                "direction" : "forward",
                                "indexBounds" : {
                                        "d" : [
                                                "[4.0, 4.0]"
                                        ]
                                }
                        }
                },

抱歉,我无法发布allPlansExecution,因为它超出了正文字数限制

此外,db.inter.find({a:1,b:2})的获胜计划也仅使用一个指数b_1_c_1

有人可以提供这些结果的解释吗?另外一个展示索引交叉点的实际例子会很有帮助。

mongodb indexing mongo-shell
1个回答
1
投票

有关指数交叉点的信息,请查看this jira票证:

当满足以下条件时,查询优化器可以选择索引交叉点计划:

  1. 相关集合中的大多数文档都是磁盘驻留的。索引交集的优点是当交叉点的大小很小时,它可以避免获取完整的文档。如果文档已经在内存中,则无法通过避免获取来获取任何内容。
  2. 查询谓词是单点间隔,而不是范围谓词或一组间隔。单点间隔的查询返回按磁盘位置排序的文档,这允许优化器选择以非阻塞方式计算交集的计划。这通常比计算交集的替代模式更快,即使用来自一个索引的结果构建哈希表,然后使用来自第二索引的结果来探测它。
  3. 要交叉的指数都不是高度选择性的。如果其中一个索引是选择性的,那么优化器将选择一个简单扫描该选择性索引的计划。
  4. 相对于单索引解决方案扫描的索引键的数量,交集的大小较小。在这种情况下,查询执行程序可以使用索引交集来查看较小的文档集,这可能使我们从磁盘中获得更少的提取。

显然,mongodb在大多数情况下可以做得更好而不使用索引,并且它选择拒绝交叉计划。很难想出一个确保mongodb将使用交叉点的例子。

对于您的示例,如果您看到以下查询的rejectedPlans:

db.intersection.explain().find({a:1,b:2,d:4});

你会发现这是计划之一(mongodb 3.4):

{
    "stage" : "FETCH",
    "filter" : {
        "$and" : [
            {
                "d" : {
                    "$eq" : 4
                }
            },
            {
                "a" : {
                    "$eq" : 1
                }
            },
            {
                "b" : {
                    "$eq" : 2
                }
            }
        ]
    },
    "inputStage" : {
        "stage" : "AND_SORTED",
        "inputStages" : [
            {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "d" : 1
                },
                "indexName" : "d_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "d" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "d" : [
                        "[4.0, 4.0]"
                    ]
                }
            },
            {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "a" : 1
                },
                "indexName" : "a_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "a" : [ ]
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "a" : [
                        "[1.0, 1.0]"
                    ]
                }
            }
        ]
    }
}

这个(AND_SORTED阶段)意味着mongodb确实考虑了索引交集作为一种可能性,但结论是d_1指数会表现得更好。

看看这些答案:herehere

© www.soinside.com 2019 - 2024. All rights reserved.