Простой запрос MongoDB очень медленный, хотя индекс установлен - PullRequest
2 голосов
/ 16 марта 2012

У меня есть коллекция MongoDB, которая содержит около 100 миллионов документов.

Документы в основном выглядят так:

_id             : ObjectId("asd1234567890")
_reference_1_id : ObjectId("fgh4567890123")
_reference_2_id : ObjectId("jkl7890123456")
name            : "Test1"
id              : "4815162342"
created_time    : Date( 1331882436000 )
_contexts       : ["context1", "context2"]
...

Есть несколько установленных индексов, вот вывод db.mycoll.getIndexes ();

[
{
    "v" : 1,
    "key" : {
        "_id" : 1
    },
    "ns" : "mydb.mycoll",
    "name" : "_id_"
},
{
    "v" : 1,
    "key" : {
        "_reference_1_id" : 1,
        "_reference_2_id" : 1,
        "id" : 1
    },
    "unique" : true,
    "ns" : "mydb.mycoll",
    "name" : "_reference_1_id_1__reference_2_id_1_id_1"
},
{
    "v" : 1,
    "key" : {
        "_reference_1_id" : 1,
        "_reference_2_id" : 1,
        "_contexts" : 1,
        "created_time" : 1
    },
    "ns" : "mydb.mycoll",
    "name" : "_reference_1_id_1__reference_2_id_1__contexts_1_created_time_1"
}
]

Когда я выполняю запрос как

db.mycoll.find({"_reference_2_id" : ObjectId("jkl7890123456")})

Это займет более часа (!) До его завершения, независимо от того, есть результаты или нет. Есть идеи?

Обновление: Вот какой вывод

db.mycoll.find({"_reference_2_id" : ObjectId("jkl7890123456")}).explain();

выглядит так:

{
"cursor" : "BasicCursor",
"nscanned" : 99209163,
"nscannedObjects" : 99209163,
"n" : 5007,
"millis" : 5705175,
"nYields" : 17389,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {

}
}

Ответы [ 3 ]

10 голосов
/ 16 марта 2012

У вас нет индекса, который mongo будет автоматически использовать для этого, поэтому он выполняет полное сканирование таблицы.

Как уже упоминалось в документах

Если первый ключ [индекса] отсутствует в запросе, индекс будет использоваться только в случае явной подсказки.

Почему

Если у вас есть индекс для a, b - и вы ищете только по a - индекс будет использоваться автоматически.Это потому, что это начало индекса (что быстро), БД может просто игнорировать остальную часть значения индекса.

Индекс для a, b равен неэффективен при поиске только по b просто потому, что он не дает возможности использовать поиск по индексу с "начинается с thisfixedstring".

Итак, либо:

  • Включить _reference_1_id в запрос (вероятно, не имеет значения)
  • ИЛИ добавить индекс _reference_2_id (если вы часто запрашиваете по полю)
  • ИЛИ используйте подсказку

Подсказка

Возможно, ваш самый дешевый вариант прямо сейчас.

Добавьте подсказку запроса в forceиспользуя ваш _reference_1_id_1__reference_2_id_1_id_1 индекс.Что, вероятно, будет намного быстрее, чем полное сканирование таблицы, но все же намного медленнее, чем индекс, который начинается с поля, которое вы используете в запросе.

т.е.

db.mycoll
    .find({"_reference_2_id" : ObjectId("jkl7890123456")})
    .hint("_reference_1_id_1__reference_2_id_1_id_1");
0 голосов
/ 05 апреля 2012

Х, У меня та же проблема на эквивалентном количестве данных. В документации написано, что запросы с индексом должны соответствовать ram. Я думаю, что это не так, запрос должен делать много дискового доступа, чтобы сначала получить индекс, а затем получить значение. В вашем случае прямое чтение коллекции будет быстрее.

EV.

0 голосов
/ 16 марта 2012

Я бы попробовал установить неуникальный индекс на _reference_2_id, потому что в настоящий момент я подозреваю, что вы будете делать эквивалент полного сканирования таблицы, поскольку даже если индексы содержат _reference_2_id, они не будут использоваться (см. здесь ).

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