Что такое multiKeyPaths в объяснении, и почему отсутствие этого приводит к неправильному использованию индекса
У меня есть большая коллекция с 4 осколками.
Когда я запускаю запрос к индексируемому массиву, поле "array.number" выглядит так:
var query = { "array" : { $elemMatch: { "number" : { $gte : "10", $lt : "20" } } } };
и проверить explain
Я получу эти планы на выигрыш (сокращенно для ясности):
Осколки 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\")"
]
}
}
Таким образом, shard1 дает ожидаемое оптимальное использование индекса, ограничивая inputStage только 10-20, в то время как другие сегменты используют только нижнюю границу индекса. Единственная разница между осколками объектов multiKeyPaths
часть, которая отсутствует в осколках 0/2/3.
Любая идея, почему это так, и как мы можем заставить другие наши шарды правильно использовать наш индекс?
ОБНОВИТЬ
Вот полный ответ объяснения для следующего запроса:
var query = { "array" : { $elemMatch: { "number" : { $gte : "10", $lt : "20" } } } };
db.collection.find(query).explain()
Отклик:
{
"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
}