为什么MongoDB不使用索引交集?

为什么MongoDB不使用索引交集?,mongodb,indexing,database-indexes,mongodb-indexes,Mongodb,Indexing,Database Indexes,Mongodb Indexes,我试图重现索引交叉指令的第一个示例,但面临一个问题:mongo不同时使用两个索引 我的步骤: 下载mongo 3.0.3并安装它 运行mongod:mongod.exe-dbpath d:\data文件夹为空 运行mongo:mongo.exe 添加索引: db.orders.ensureIndex({ qty: 1 }) db.orders.ensureIndex({ item: 1 }) db.orders.getIndexes() [{ "v" : 1, "

我试图重现索引交叉指令的第一个示例,但面临一个问题:mongo不同时使用两个索引

我的步骤:

下载mongo 3.0.3并安装它 运行mongod:mongod.exe-dbpath d:\data文件夹为空 运行mongo:mongo.exe 添加索引:

db.orders.ensureIndex({ qty: 1 })
db.orders.ensureIndex({ item: 1 })
db.orders.getIndexes()
[{
        "v" : 1,
        "key" : {
                "_id" : 1
        },
        "name" : "_id_",
        "ns" : "test.orders"
},
{
        "v" : 1,
        "key" : {
                "qty" : 1
        },
        "name" : "qty_1",
        "ns" : "test.orders"
},
{
        "v" : 1,
        "key" : {
                "item" : 1
        },
        "name" : "item_1",
        "ns" : "test.orders"
}]
检查查询解释:

db.orders.find( { item: "abc123", qty: { $gt: 15 } } ).explain()
{
    "queryPlanner" : {
            "plannerVersion" : 1,
            "namespace" : "test.orders",
            "indexFilterSet" : false,
            "parsedQuery" : {
                    "$and" : [
                            {
                                    "item" : {
                                            "$eq" : "abc123"
                                    }
                            },
                            {
                                    "qty" : {
                                            "$gt" : 15
                                    }
                            }
                    ]
            },
            "winningPlan" : {
                    "stage" : "KEEP_MUTATIONS",
                    "inputStage" : {
                            "stage" : "FETCH",
                            "filter" : {
                                    "qty" : {
                                            "$gt" : 15
                                    }
                            },
                            "inputStage" : {
                                    "stage" : "IXSCAN",
                                    "keyPattern" : {
                                            "item" : 1
                                    },
                                    "indexName" : "item_1",
                                    "isMultiKey" : false,
                                    "direction" : "forward",
                                    "indexBounds" : {
                                            "item" : [
                                                    "[\"abc123\", \"abc123\"]"
                                            ]
                                    }
                            }
                    }
            },
            "rejectedPlans" : [
                    {
                            "stage" : "KEEP_MUTATIONS",
                            "inputStage" : {
                                    "stage" : "FETCH",
                                    "filter" : {
                                            "item" : {
                                                    "$eq" : "abc123"
                                            }
                                    },
                                    "inputStage" : {
                                            "stage" : "IXSCAN",
                                            "keyPattern" : {
                                                    "qty" : 1
                                            },
                                            "indexName" : "qty_1",
                                            "isMultiKey" : false,
                                            "direction" : "forward",
                                            "indexBounds" : {
                                                    "qty" : [
                                                            "(15.0, 1.#INF]"
                                                    ]
                                            }
                                    }
                            }
                    }
            ]
    },
    "serverInfo" : {
            "host" : "localhost",
            "port" : 27017,
            "version" : "3.0.3",
            "gitVersion" : "b40106b36eecd1b4407eb1ad1af6bc60593c6105"
    },
    "ok" : 1
}
正如您所看到的,winningPlan只包含项_1索引。存在包含数量1索引的拒绝计划。但没有包含索引交叉点的计划。 我知道选择具体指标有很多条件。但就我而言,mongo甚至没有计划


有人能帮我吗?

中有一些关于索引选择的详细信息,但我不能说这些是否仍然与3.0相关。无论如何:

MangGDB 3.0.2似乎不考虑范围查询的索引交互。但对于点间距,它将:

> db.orders.find( { item: {$eq : "abc123"}, qty: { $eq: 15 } } ).explain()
...

        {
            "stage" : "FETCH",
            "inputStage" : {
                "stage" : "KEEP_MUTATIONS",
                "inputStage" : {
                    "stage" : "AND_SORTED",
                    "inputStages" : [
                        {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "qty" : 1
                            },
                            "indexName" : "qty_1",
                            "isMultiKey" : false,
                            "direction" : "forward",
                            "indexBounds" : {
                                "qty" : [
                                    "[15.0, 15.0]"
                                ]
                            }
                        },
                        {
                            "stage" : "IXSCAN",
                            "keyPattern" : {
                                "item" : 1
                            },
                            "indexName" : "item_1",
                            "isMultiKey" : false,
                            "direction" : "forward",
                            "indexBounds" : {
                                "item" : [
                                    "[\"abc123\", \"abc123\"]"
                                ]
                            }
                        }
                    ]
                }

我们正在托管一个多租户网站。所以有一个mongo集合,它保存了一些关于所有客户的信息,例如

{customerId: 22, category: "category", region: "region", balance: 23434... }
在了解了索引交集之后,我们尝试创建多个单字段索引,以支持具有可变字段的不同查询条件的查询,例如

{ customerId: 22, category: "1" }
{ customerId: 22, region: "somewhere" }
{ customerId: 22, balance: {$gt:0} }
{ customerId: 22, region: {$in: ["R1", "R2"]},balance: {$gt:0} }
....
但事实证明,从db.collection.explain学习并没有发生交叉。 由于字段有限,我们最终找到了一个解决方案,即构建一个包含所有字段的复合索引

{customerId: 1, category: 1, region: 1, balance:1...}
然后发现,就查询中的customerId而言,下面所有查询都使用大型复合索引

{ customerId: 22, category: "1" }
{ customerId: 22, region: "somewhere" }
{ customerId: 22, balance: {$gt:0} }
{ customerId: 22, region: {$in: ["R1", "R2"]},balance: {$gt:0} }
....

FWIW与MongoDB 3.0.2的工作原理相同。数据库中有多少文档?解释说什么?查询需要多长时间?如果有的话,数据字段的分布是什么?那么,在现实生活中,基本上索引相交似乎从未发生过?根据我的测试,对$in查询中超过1项也不起作用:观察与v3.4.10相同的行为进一步观察:提示对复合索引前缀不起作用仅对整个复合索引起作用;索引交集似乎不适用于复合索引前缀,仅适用于单个索引。不过,仅仅添加这么大的复合索引并没有多大帮助。在您提供的四个查询示例中,后三个仅使用复合索引的customerId前缀,而第一个使用复合索引的customerId加上类别前缀。如果您试图为这四个查询建立索引,那么只在前两个字段上建立复合索引会更好。只是说,没有人会想到,一个庞大的复合索引会加速对其中任何字段的任意查询过滤: