1

I have a large collection with 4 shards.

When I run a query over an indexed array field "array.number" like so:

var query = { "array" : { $elemMatch: { "number" : { $gte : "10", $lt : "20" } } } };

and check explain, I'll get these winning plans (abbreviated for clarity):

Shards 0/2/3:

"inputStage": {
  "stage": "IXSCAN",
  ...
  "isMultiKey": true,
  "indexBounds": {
    "array.number": [
      "[\"10\", {})"
    ]
  }
}

Shard1:

"inputStage": {
  "stage": "IXSCAN",
  ...
  "isMultiKey": true,
  "multiKeyPaths": {
    "array.number": [
      "array"
    ]
  },
  "indexBounds": {
    "array.number": [
      "[\"10\", \"20\")"
    ]
  }
}

So shard1 gives the expected optimal use of the index, limiting the inputStage to go over 10-20 only, while the other shards only use the lower bound on the index. The only difference between the shards objects is the multiKeyPaths part, which is missing in shards 0/2/3.

Any idea why is that, and how we can cause our other shards to properly use our index?

UPDATE

Here's the full explain response for the following query:

var query = { "array" : { $elemMatch: { "number" : { $gte : "10", $lt : "20" } } } };
db.collection.find(query).explain()

Response:

{
    "queryPlanner" : {
        "mongosPlannerVersion" : 1,
        "winningPlan" : {
            "stage" : "SHARD_MERGE",
            "shards" : [ 
                {
                    "shardName" : "company_rs0",
                    "connectionString" : "company_rs0/shard0-db0:27017,shard0-db1:27017",
                    "serverInfo" : {"host":"shard0-db0","port":27017,"version":"3.4.7","gitVersion":"cf38c1b8a0a8dca4a11737581beafef4fe120bcd"},
                    "plannerVersion" : 1,
                    "namespace" : "company_database.collection",
                    "indexFilterSet" : false,
                    "parsedQuery" : {"array":{"$elemMatch":{"$and":[{"number":{"$lt":"20"}},{"number":{"$gte":"10"}}]}}},
                    "winningPlan" : {
                        "stage" : "FETCH",
                        "filter" : {
                            "array" : {
                                "$elemMatch" : {"$and":[{"number":{"$gte":"10"}},{"number":{"$lt":"20"}}]}
                            }
                        },
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "numberPattern" : {"array.number":1.0},
                            "indexName" : "array.number_1",
                            "isMultiKey" : true,
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 1,
                            "direction" : "forward",
                            "indexBounds" : {"array.number":["[\"10\", {})"]}
                        }
                    },
                    "rejectedPlans" : [ 
                        {
                            "stage" : "FETCH",
                            "filter" : {
                                "array" : {"$elemMatch":{"$and":[{"number":{"$lt":"20"}},{"number":{"$gte":"10"}}]}}
                            },
                            "inputStage" : {
                                "stage" : "IXSCAN",
                                "numberPattern" : {"array.number":1.0},
                                "indexName" : "array.number_1",
                                "isMultiKey" : true,
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 1,
                                "direction" : "forward",
                                "indexBounds" : {"array.number":["[\"\", \"20\")"]}
                            }
                        }
                    ]
                }, 
                {
                    "shardName" : "company_rs1",
                    "connectionString" : "company_rs1/shard1-db0:27017,shard1-db1:27017",
                    "serverInfo" : {"host":"shard1-db0","port":27017,"version":"3.4.7","gitVersion":"cf38c1b8a0a8dca4a11737581beafef4fe120bcd"},
                    "plannerVersion" : 1,
                    "namespace" : "company_database.collection",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "array" : {"$elemMatch":{"$and":[{"number":{"$lt":"20"}},{"number":{"$gte":"10"}}]}}
                    },
                    "winningPlan" : {
                        "stage" : "FETCH",
                        "filter" : {
                            "array" : {"$elemMatch":{"$and":[{"number":{"$lt":"20"}},{"number":{"$gte":"10"}}]}}
                        },
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "numberPattern" : {"array.number":1.0},
                            "indexName" : "array.number_1",
                            "isMultiKey" : true,
                            "multiKeyPaths" : {"array.number":["array"]},
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 1,
                            "direction" : "forward",
                            "indexBounds" : {"array.number":["[\"10\", \"20\")"]}
                        }
                    },
                    "rejectedPlans" : []
                }, 
                {
                    "shardName" : "company_rs2",
                    "connectionString" : "company_rs2/shard2-db0:27017,shard2-db1:27017",
                    "serverInfo" : {"host":"shard2-db0","port":27017,"version":"3.4.7","gitVersion":"cf38c1b8a0a8dca4a11737581beafef4fe120bcd"},
                    "plannerVersion" : 1,
                    "namespace" : "company_database.collection",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "array" : {"$elemMatch":{"$and":[{"number":{"$lt":"20"}},{"number":{"$gte":"10"}}]}}
                    },
                    "winningPlan" : {
                        "stage" : "FETCH",
                        "filter" : {
                            "array" : {"$elemMatch":{"$and":[{"number":{"$gte":"10"}},{"number":{"$lt":"20"}}]}}
                        },
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "numberPattern" : {"array.number":1.0},
                            "indexName" : "array.number_1",
                            "isMultiKey" : true,
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 1,
                            "direction" : "forward",
                            "indexBounds" : {"array.number":["[\"10\", {})"]}
                        }
                    },
                    "rejectedPlans" : [ 
                        {
                            "stage" : "FETCH",
                            "filter" : {
                                "array" : {"$elemMatch":{"$and":[{"number":{"$lt":"20"}},{"number":{"$gte":"10"}}]}}
                            },
                            "inputStage" : {
                                "stage" : "IXSCAN",
                                "numberPattern" : {"array.number":1.0},
                                "indexName" : "array.number_1",
                                "isMultiKey" : true,
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 1,
                                "direction" : "forward",
                                "indexBounds" : {"array.number":["[\"\", \"20\")"]}
                            }
                        }
                    ]
                }, 
                {
                    "shardName" : "company_rs3",
                    "connectionString" : "company_rs3/shard3-db0:27017,shard3-db1:27017",
                    "serverInfo" : {"host":"shard3-db0","port":27017,"version":"3.4.7","gitVersion":"cf38c1b8a0a8dca4a11737581beafef4fe120bcd"},
                    "plannerVersion" : 1,
                    "namespace" : "company_database.collection",
                    "indexFilterSet" : false,
                    "parsedQuery" : {
                        "array" : {"$elemMatch":{"$and":[{"number":{"$lt":"20"}},{"number":{"$gte":"10"}}]}}
                    },
                    "winningPlan" : {
                        "stage" : "FETCH",
                        "filter" : {
                            "array" : {"$elemMatch":{"$and":[{"number":{"$gte":"10"}},{"number":{"$lt":"20"}}]}}
                        },
                        "inputStage" : {
                            "stage" : "IXSCAN",
                            "numberPattern" : {"array.number":1.0},
                            "indexName" : "array.number_1",
                            "isMultiKey" : true,
                            "isUnique" : false,
                            "isSparse" : false,
                            "isPartial" : false,
                            "indexVersion" : 1,
                            "direction" : "forward",
                            "indexBounds" : {"array.number":["[\"10\", {})"]}
                        }
                    },
                    "rejectedPlans" : [ 
                        {
                            "stage" : "FETCH",
                            "filter" : {
                                "array" : {"$elemMatch":{"$and":[{"number":{"$lt":"20"}},{"number":{"$gte":"10"}}]}}
                            },
                            "inputStage" : {
                                "stage" : "IXSCAN",
                                "numberPattern" : {"array.number":1.0},
                                "indexName" : "array.number_1",
                                "isMultiKey" : true,
                                "isUnique" : false,
                                "isSparse" : false,
                                "isPartial" : false,
                                "indexVersion" : 1,
                                "direction" : "forward",
                                "indexBounds" : {"array.number":["[\"\", \"20\")"]}
                            }
                        }
                    ]
                }
            ]
        }
    },
    "ok" : 1.0
}
marmor
  • 27,641
  • 11
  • 107
  • 150
  • Are all of your shards actually running 3.4.x? Or are some on a lower version? – Neil Lunn Oct 30 '17 at 11:57
  • yes, all are on 3.4.7 – marmor Oct 30 '17 at 13:14
  • I never encountered `multiKeyPaths` and it seems like something to do with mongodb internals, but are you sure this index exists on all shards? This query is a fairly simple one and it should use those index bounds, unless you have anything additional in your query – Meni Oct 30 '17 at 21:53
  • What's the shard key on the collection? Can you also include the more complete explain output as well. Really need to see that there is nothing else interfering with the selection, so also really want to be sure that the query options being issued are the only query parameters being issued. In short, this should be reproducible even with just 2 shards, so knowing how the data is set up as well as the actual query being issued is crucial. – Neil Lunn Oct 31 '17 at 01:31
  • @NeilLunn the shard key is `{ "_id" : "hashed" }`, I've updated the question with the full code to call `explain()`, and the full response. – marmor Oct 31 '17 at 06:41

0 Answers0