Ожидаемое поведение соединения _id в MongoDB? - PullRequest
3 голосов
/ 30 августа 2011

У меня составной _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" : {}

Без лимита () результат:

"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 верен.

Я использую релиз 1.8.3 MongoDb. Может ли кто-нибудь уточнить, вижу ли я ожидаемое поведение или неправильно понял, как использовать / запросить составной индекс?

Спасибо, Пол.

Ответы [ 2 ]

10 голосов
/ 30 августа 2011

Индекс не является составным индексом , а индексом всего значения поля _id. MongoDB не просматривает индексированное поле и вместо этого использует необработанное представление поля BSON для сравнения (если я правильно прочитал документы).

Чтобы сделать то, что вы хотите, вам нужен фактический составной индекс выше {_id.KeyA: 1, _id.KeyB: 1, _id.KeyC: 1} (который также должен быть уникальным индексом). Поскольку у вас не может не быть индекса на _id, вам, вероятно, будет лучше оставить его как ObjectId (который создаст меньший индекс и будет тратить меньше места), и сохранить ваши KeyA, KeyB и * 1011. * поля как свойства вашего документа. Например. {_id: ObjectId("xyz..."), KeyA: 1, KeyB: 2, KeyB: 3}

8 голосов
/ 30 августа 2011

Вам понадобится отдельный составной индекс для желаемого поведения.В общем, я рекомендую не использовать объекты в качестве _id, поскольку порядок сравнения значим в сравнениях, поэтому {a: 1, b: 1} не равно {b: 1, a: 1}.Поскольку не все водители сохраняют ключевой порядок в объектах, очень легко выстрелить себе в ногу, выполнив что-то вроде этого:

db.foo.save(db.foo.findOne())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...