Статьи

Запрос медленного запроса MongoDB и как пользователь ускорил работу


Почему мой запрос на mongodb такой медленный?

Я установил свою геопространственную коллекцию — я выполняю несколько действительно великолепных запросов, чтобы убедиться, что места, которые я извлекаю, не находятся в каком-либо кеше, и я просто поражен тем, как быстро  возвращаются данные.

Проблема заключается в том, что когда я запрашиваю коллекцию для получения необходимых данных lon / lat по имени: город и штат или город и страна, кажется, что выполнение запроса занимает несколько секунд  !

Я правильно настроил таблицу … Я проиндексировал дерьмо из всех своих столбцов … Неделю или две назад я был на mongoSV 2011 в Санта-Кларе и узнал некоторые действительно интересные вещи о запросах, индексации и управлении производительностью, так что давайте выкопайте заметки и посмотрите, где я ошибся. Потому что я сильно  сомневаюсь, что проблема в Монго, но, скорее, как мы говорили в технической поддержке: это проблема PBCK …

Первое, что я хочу сделать, это запустить объяснение для моего запроса, чтобы я мог видеть план запроса mongo для моего запроса. Это должно дать мне отправную точку для попытки выяснить, что пошло не так.

> db.geodata_geo.find({ cityName : “Anniston”, stateName : “Alabama” }).explain();

 Добавляя завершающую функцию: .explain () , я прошу mongoDB вернуть мне план запроса вместо выполнения запроса. Я нажимаю Enter, чтобы запустить объяснение () и получить следующий вывод:

    > db.geodata_geo.find({ cityName : “Anniston”, stateName : “Alabama”}).explain();
    {
    “cursor” : “BasicCursor“,
    “nscanned” : 3691723,
    “nscannedObjects” : 3691723,
    “n” : 1,
    “millis” : 2269,
    “nYields” : 0,
    “nChunkSkips” : 0,
    “isMultiKey” : false,
    “indexOnly” : false,
    “indexBounds” : {

    }
    }

Важную информацию я выделил жирным шрифтом в выводе запроса (выше). Этот вывод говорит мне о том, что я использовал «BasicCursor» для своего поискового курсора, что указывает на то, что да, я выполняю сканирование таблицы в коллекции. Итак, я уже знаю, что мой запрос не оптимален. Но ждать! Еще хорошие новости …

Значение для nscanned  и nscannedObjects  одинаково: 3 691 723 — что совпадает с количеством элементов коллекции. Это число — количество документов, отсканированных для выполнения запроса, которое, учитывая его значение, подтверждает, что я выполняю полное сканирование таблицы.

millis  сообщает мне количество миллисекунд, на которое запрос может занять: 2,269 секунды: это слишком медленно для моих внутренних методов (), обслуживающих REST API, — недопустимо.

И затем мы переходим к сообщению:   IndexOnly  сообщает мне, что если бы запрос мог быть решен с помощью (существующего) покрывающего индекса.  Когда я вижу значение false, это говорит о том, что в коллекции нет индекса по столбцам, которые я сканирую.

Какая?!? Я знаю,  что проиндексировал эту коллекцию …

Итак, я запускаю db.geodata_geo.getIndexes (), чтобы вывести мои индексы и … я … не вижу, что мои столбцы имен проиндексированы. О, я не забыла индексировать столбцы ID и Code … но каким-то образом индексирование столбцов Name полностью ускользнуло от моего нижнего уровня.

Я добавляю эти индексы в свою коллекцию:

> db.geodata_geo.ensureIndex({ cityName : 1 });
> db.geodata_geo.ensureIndex({ stateName : 1 });

 И тогда я повторно запускаю план запроса и вижу следующий вывод:

    > db.geodata_geo.find({ cityName : “Anniston”, stateName : “Alabama”}).explain();
    {
    “cursor” : “BtreeCursor cityName_1″,
    “nscanned” : 2,
    “nscannedObjects” : 2,
    “n” : 1,
    “millis” : 101,
    “nYields” : 0,
    “nChunkSkips” : 0,
    “isMultiKey” : false,
    “indexOnly” : false,
    “indexBounds” : {
    “cityName” : [
    [
    "Anniston",
    "Anniston"
    ]
    ]
    }
    }

 Вместо BasicCursor я вижу BtreeCursor,  который приносит мне счастье. Я также вижу, что значения nscanned  и nscannedObjects  теперь более реалистичны … серьезно: 2 много лучше, чем 3,6 миллиона, верно? Еще один рад за меня!

Я оцениваю третье счастье, когда вижу, что миллис снизился до 101: 0,101 секунды, чтобы выполнить этот поиск / запрос! Я не согласен, я согласен — но приемлемо, учитывая, что все работает на моем ноутбуке … Я знаю, что время производства будет намного, намного ниже.

В конце концов, я узнал, что простой инструмент, такой как .explain (), может сказать мне, где требуется мое внимание, когда речь идет об оптимизации и исправлении даже простых, казалось бы, невинных запросов. Знание того, на что ты смотришь, и того, что ты ищешь, в значительной степени является бейсбольной битой, когда дело доходит до того, чтобы раздавить одного из парка.

Надеюсь, это поможет!

Источник: http://shallop.com/2011/12/why-is-my-mongo-query-so-slow/