10

我正在尝试重现索引交叉指令的第一个示例(http://docs.mongodb.org/manual/core/index-intersection/)但面临一个问题:mongo 不使用两个索引

我的步骤:

  1. 下载 mongo (3.0.3) 并安装
  2. 运行 mongod:mongod.exe --dbpath d:\data(文件夹为空)
  3. 运行mongo:mongo.exe
  4. 添加索引:

    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"
    }]
    
  5. 检查查询说明:

    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
    }
    

如您所见,winingPlan 仅包含 item_1 索引。有包含 qty_1 索引的拒绝计划。但是没有包含索引交集的计划。我知道选择特定索引有很多条件。但在我的情况下,mongo 甚至没有计划它!

有人可以帮助我吗?

4

2 回答 2

4

在SERVER-3071 JIRA 问题中有一些关于索引选择的详细信息,但我不能说所有这些是否仍然与 3.0 相关。反正:

MongoDB 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\"]"
                                ]
                            }
                        }
                    ]
                }
于 2015-06-03T18:56:03.893 回答
1

我们正在托管一个多租户站点。所以有一个 mongo 集合,其中包含有关所有客户的一些信息,例如,

{customerId: 22, category: "category", region: "region", balance: 23434... }

了解了Index Intersection之后,我们尝试创建多个单字段索引,以支持不同查询条件和可变字段的查询,例如

{ 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} }
....
于 2017-06-30T08:31:13.540 回答