tl; dr
- Я установил индексы, которые можно использовать в качестве пересечения индексов для моего запроса
- Планировщик запросов не предпочитает пересечение из-за недостатка данных
- Теперь мне нужен стабильный способ проверки правильности этого потенциала плана пересечения, аналогично использованию
explain()
hint()
для единственного индекса
Я полностью понимаю, почему пересечение индекса не является предпочтительным atm и может фактически не быть предпочтительным в большинстве случаев.Но я просто ищу способ проверки пересечения индексов в целом.
========
У меня есть коллекция notifications
, в которой хранятся такие документы, как
{
"_id": ObjectId("5cdd1819c1136c394a052aa2"),
"notifiable": DBRef("users", ObjectId("5cdd172ac1136c1bdc06bdf2")),
"read_at": ISODate("2019-05-16T07:59:17.985Z")
}
... и он получает следующие индексы:
[
{
"v" : 2,
"key" : {
"notifiable.$id" : 1,
"notifiable.$ref" : 1,
"created_at" : -1,
"updated_at" : -1
},
"name" : "notifiable.$id_1_notifiable.$ref_1_created_at_-1_updated_at_-1",
"ns" : "example.notifications"
},
{
"v" : 2,
"key" : {
"read_at" : 1
},
"name" : "read_at_1",
"ns" : "example.notifications"
}
]
Когда я запускаю запросы, например,
db.notifications.find({ read_at: { $gt: ISODate("2019-05-16T07:55:57.799Z") }, "notifiable.$id": ObjectId("5cdd172ac1136c1bdc06bdf2") })
... Я ожидаю, что MongoDB будет использоватьпересечение этих двух индексов, когда это необходимо.Но поскольку MongoDB принимает во внимание множество факторов, чтобы определить, следует ли использовать пересечение индексов , для моего запроса использовался только 1 индекс (возможно, потому что в коллекции было всего несколько документов) и дажерезультат explain(true)
не имел стадии AND_SORTED
AND_HASH
:
{
"queryPlanner": {
"plannerVersion": 1,
"namespace": "example.notifications",
"indexFilterSet": false,
"parsedQuery": {
"$and": [{
"notifiable.$id": {
"$eq": ObjectId("5cdd172ac1136c1bdc06bdf2")
}
},
{
"read_at": {
"$gt": ISODate("2019-05-16T07:55:57.799Z")
}
}
]
},
"winningPlan": {
"stage": "FETCH",
"filter": {
"notifiable.$id": {
"$eq": ObjectId("5cdd172ac1136c1bdc06bdf2")
}
},
"inputStage": {
"stage": "IXSCAN",
"keyPattern": {
"read_at": 1
},
"indexName": "read_at_1",
"isMultiKey": false,
"multiKeyPaths": {
"read_at": []
},
"isUnique": false,
"isSparse": false,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"read_at": [
"(new Date(1557993357799), new Date(9223372036854775807)]"
]
}
}
},
"rejectedPlans": [{
"stage": "FETCH",
"filter": {
"read_at": {
"$gt": ISODate("2019-05-16T07:55:57.799Z")
}
},
"inputStage": {
"stage": "IXSCAN",
"keyPattern": {
"notifiable.$id": 1,
"notifiable.$ref": 1,
"created_at": -1,
"updated_at": -1
},
"indexName": "notifiable.$id_1_notifiable.$ref_1_created_at_-1_updated_at_-1",
"isMultiKey": false,
"multiKeyPaths": {
"notifiable.$id": [],
"notifiable.$ref": [],
"created_at": [],
"updated_at": []
},
"isUnique": false,
"isSparse": false,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"notifiable.$id": [
"[ObjectId('5cdd172ac1136c1bdc06bdf2'), ObjectId('5cdd172ac1136c1bdc06bdf2')]"
],
"notifiable.$ref": [
"[MinKey, MaxKey]"
],
"created_at": [
"[MaxKey, MinKey]"
],
"updated_at": [
"[MaxKey, MinKey]"
]
}
}
}]
},
"executionStats": {
"executionSuccess": true,
"nReturned": 1,
"executionTimeMillis": 0,
"totalKeysExamined": 2,
"totalDocsExamined": 2,
"executionStages": {
"stage": "FETCH",
"filter": {
"notifiable.$id": {
"$eq": ObjectId("5cdd172ac1136c1bdc06bdf2")
}
},
"nReturned": 1,
"executionTimeMillisEstimate": 0,
"works": 4,
"advanced": 1,
"needTime": 1,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"docsExamined": 2,
"alreadyHasObj": 0,
"inputStage": {
"stage": "IXSCAN",
"nReturned": 2,
"executionTimeMillisEstimate": 0,
"works": 3,
"advanced": 2,
"needTime": 0,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"keyPattern": {
"read_at": 1
},
"indexName": "read_at_1",
"isMultiKey": false,
"multiKeyPaths": {
"read_at": []
},
"isUnique": false,
"isSparse": false,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"read_at": [
"(new Date(1557993357799), new Date(9223372036854775807)]"
]
},
"keysExamined": 2,
"seeks": 1,
"dupsTested": 0,
"dupsDropped": 0,
"seenInvalidated": 0
}
},
"allPlansExecution": [{
"nReturned": 1,
"executionTimeMillisEstimate": 0,
"totalKeysExamined": 2,
"totalDocsExamined": 2,
"executionStages": {
"stage": "FETCH",
"filter": {
"notifiable.$id": {
"$eq": ObjectId("5cdd172ac1136c1bdc06bdf2")
}
},
"nReturned": 1,
"executionTimeMillisEstimate": 0,
"works": 3,
"advanced": 1,
"needTime": 1,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"docsExamined": 2,
"alreadyHasObj": 0,
"inputStage": {
"stage": "IXSCAN",
"nReturned": 2,
"executionTimeMillisEstimate": 0,
"works": 3,
"advanced": 2,
"needTime": 0,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"keyPattern": {
"read_at": 1
},
"indexName": "read_at_1",
"isMultiKey": false,
"multiKeyPaths": {
"read_at": []
},
"isUnique": false,
"isSparse": false,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"read_at": [
"(new Date(1557993357799), new Date(9223372036854775807)]"
]
},
"keysExamined": 2,
"seeks": 1,
"dupsTested": 0,
"dupsDropped": 0,
"seenInvalidated": 0
}
}
},
{
"nReturned": 1,
"executionTimeMillisEstimate": 0,
"totalKeysExamined": 2,
"totalDocsExamined": 2,
"executionStages": {
"stage": "FETCH",
"filter": {
"read_at": {
"$gt": ISODate("2019-05-16T07:55:57.799Z")
}
},
"nReturned": 1,
"executionTimeMillisEstimate": 0,
"works": 3,
"advanced": 1,
"needTime": 1,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"docsExamined": 2,
"alreadyHasObj": 0,
"inputStage": {
"stage": "IXSCAN",
"nReturned": 2,
"executionTimeMillisEstimate": 0,
"works": 3,
"advanced": 2,
"needTime": 0,
"needYield": 0,
"saveState": 0,
"restoreState": 0,
"isEOF": 1,
"invalidates": 0,
"keyPattern": {
"notifiable.$id": 1,
"notifiable.$ref": 1,
"created_at": -1,
"updated_at": -1
},
"indexName": "notifiable.$id_1_notifiable.$ref_1_created_at_-1_updated_at_-1",
"isMultiKey": false,
"multiKeyPaths": {
"notifiable.$id": [],
"notifiable.$ref": [],
"created_at": [],
"updated_at": []
},
"isUnique": false,
"isSparse": false,
"isPartial": false,
"indexVersion": 2,
"direction": "forward",
"indexBounds": {
"notifiable.$id": [
"[ObjectId('5cdd172ac1136c1bdc06bdf2'), ObjectId('5cdd172ac1136c1bdc06bdf2')]"
],
"notifiable.$ref": [
"[MinKey, MaxKey]"
],
"created_at": [
"[MaxKey, MinKey]"
],
"updated_at": [
"[MaxKey, MinKey]"
]
},
"keysExamined": 2,
"seeks": 1,
"dupsTested": 0,
"dupsDropped": 0,
"seenInvalidated": 0
}
}
}
]
},
"ok": 1,
"operationTime": Timestamp(1557996666, 2),
"$clusterTime": {
"clusterTime": Timestamp(1557996666, 2),
"signature": {
"hash": BinData(0, "hDKqoIo9DL71/n8vfgSDS3czZ9c="),
"keyId": NumberLong("6685056801689305089")
}
}
}
Я попробовал пример orders
из https://docs.mongodb.com/v4.0/core/index-intersection/ и получил те же результаты.И поскольку MongoDB в настоящее время не позволяет использовать несколько индексов в качестве подсказки , я не могу принудить MongoDB использовать оба индекса для моего запроса.Что еще хуже, ранее explain(true)
всегда включало бы что-то вроде "cursor" : "Complex Plan"
, когда были доступны планы пересечения индексов ( Почему MongoDB не использует пересечение индексов? ), но теперь эта информация была удалена.
Так как я могу знать, когда, возможно, достаточно данных, будет ли использоваться пересечение индексов или нет?
PS: я использую MongoDB Atlas, который работает под управлением MongoDB 4.0.9 Предприятие атм.