У меня есть коллекция записей, среди которых есть primary_id (уникальный), вторичный_ид, поля состояния. Идентификаторы представляют собой буквенно-цифровые поля (например, «ABCD0000»), а статус - числовой (1 - 5).
Один из часто используемых запросов - это фильтрация по id (равенство или диапазон) и статусу.
Примеры:
- записей, где primary_id между 'ABCD0000' - 'ABCN0000' и статусом 2 или 3, сортировка по primary_id.
- записывает, где вторичный_ид между 'ABCD0000' - 'ABCD0000' и статусом 2 или 3, сортировка по primary_id (или вторичному_id, если это поможет).
Статус в фильтре в основном будет (статус в (2,3)).
Первоначально у нас был один индекс для каждого из полей. Но запрос истекает, когда диапазон большой. Я попытался добавить несколько индексов (одиночных и составных) и разными способами написать фильтр, но не смог добиться достойной производительности. Теперь у меня есть эти индексы:
[
{primary_id: 1},
{secondary_id: 1},
{status: 1},
{primary_id: 1, status: 1},
{status: 1, primary_id: 1},
{status: 1, secondary_id: 1}
]
Этот запрос (с или без сортировки по primary_id)
{ $and: [
{ primary_id: { $gte: 'ABCD0000' } },
{ primary_id: { $lte: 'ABCN0000' } },
{status: { $in: [2,3] } }
] }
используйте следующий план:
...
"winningPlan" : {
"stage" : "FETCH",
"filter" : {
"status" : {
"$in" : [
2,
3
]
}
},
"inputStage" : {
"stage" : "IXSCAN",
"keyPattern" : {
"primary_id" : 1
},
"indexName" : "primary_idx",
"isMultiKey" : false,
"multiKeyPaths" : {
"primary_id" : [ ]
},
"isUnique" : true,
"isSparse" : false,
"isPartial" : false,
"indexVersion" : 2,
"direction" : "forward",
"indexBounds" : {
"primary_id" : [
"[\"ABCD0000\", \"ABCN0000\"]"
]
}
}
},
Итак, кажется, что шаг FETCH занимает много времени, если количество возвращаемых строк велико. Удивительно, что при выполнении начальных тестов состояния составной индекс primary_id иногда выбирался как выигрышный план, и это было очень быстро (несколько секунд). Но по какой-то причине Монго его больше не выбирал. Я думаю, когда запрос должен быть отсортирован по primary_id, этот составной индекс не будет выбран, как я понял из документов Mongo
Если в запросе не указано условие равенства для префикса индекса, который предшествует или перекрывается со спецификацией сортировки, операция не будет эффективно использовать индекс.
Я пытался изменить запрос, как показано ниже, но он все еще не оптимизирован
{$or: [
{ $and: [ { primary_id: { $gte: 'ABCD0000' } }, { primary_id: { $lte: 'ABCN0000' } }, { status: 2 } ]},
{ $and: [ { primary_id: { $gte: 'ABCD0000' } }, { primary_id: { $lte: 'ABCN0000' } }, { status: 3 } ]}
]}
Какие-либо предложения о том, что будет лучшей стратегией индексирования или запроса?