У меня есть составной _id, содержащий 3 числовых свойства:
_id ": {" KeyA ": 0," KeyB ": 0," KeyC ": 0}
Рассматриваемая база данных имеет 2 миллиона идентичных значений для KeyA и кластеры по 500 000 идентичных значений для KeyB.
Насколько я понимаю, я могу эффективно запрашивать KeyA и KeyB с помощью команды:
find( { "_id.KeyA" : 1, "_id.KeyB": 3 } ).limit(100)
Когда я объясняю этот запрос, результат:
"cursor" : "BasicCursor",
"nscanned" : 1000100,
"nscannedObjects" : 1000100,
"n" : 100,
"millis" : 1592,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {}
Без limit () результат будет:
"cursor" : "BasicCursor",
"nscanned" : 2000000,
"nscannedObjects" : 2000000,
"n" : 500000,
"millis" : 3181,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {}
Насколько я понимаю, BasicCursor означает, что индекс был проигнорирован, и оба запроса имеют большое время выполнения - даже когда я запросил только 100 записей, это занимает ~ 1,5 секунды. Я намеревался использовать ограничение для реализации разбивки на страницы, но это явно слишком медленно.
Команда:
find( { "_id.KeyA" : 1, "_id.KeyB": 3, , "_id.KeyC": 1000 } )
Правильно использует BtreeCursor и быстро выполняет, предлагая правильное составное _id.
Я использую MongoDb версии 1.8.3. Может ли кто-нибудь уточнить, вижу ли я ожидаемое поведение или неправильно понял, как использовать / запрашивать составной индекс?
Спасибо, Пол.
2 ответа
Индекс не является составным индексом, а является индексом всего значения поля _id
. MongoDB не смотрит в индексированное поле, а вместо этого использует необработанное представление поля BSON для сравнения (если я правильно прочитал документы).
Чтобы делать то, что вы хотите, вам нужен фактический составной индекс по {_id.KeyA: 1, _id.KeyB: 1, _id.KeyC: 1}
(который также должен быть уникальным индексом). Поскольку у вас не может быть индекса для _id
, вам, вероятно, будет лучше оставить его как ObjectId
(что приведет к уменьшению индекса и потере места) и сохраните свой KeyA
, Поля KeyB
и KeyC
как свойства вашего документа. Например. {_id: ObjectId("xyz..."), KeyA: 1, KeyB: 2, KeyB: 3}
Вам понадобится отдельный составной индекс для желаемого поведения. В общем, я не рекомендую использовать объекты в качестве _id, потому что порядок ключей важен при сравнении, поэтому {a: 1, b: 1} не равно {b: 1, a: 1}. Поскольку не все водители сохраняют ключевой порядок в объектах, очень легко выстрелить себе в ногу, сделав что-то вроде этого:
db.foo.save(db.foo.findOne())
Похожие вопросы
Связанные вопросы
Новые вопросы
mongodb
MongoDB - это масштабируемая, высокопроизводительная база данных NoSQL с открытым исходным кодом, ориентированная на документы. Он поддерживает большое количество языков и платформ разработки приложений. Вопросы по администрированию сервера можно задать на https://dba.stackexchange.com.