Почему и когда необходимо перестраивать индексы в MongoDB?

Некоторое время работал с MongoDB, и сегодня у меня возникли сомнения при обсуждении с коллегой.

Дело в том, что когда вы создаете индекс в MongoDB, коллекция обрабатывается и индекс строится.

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

Согласно документации MongoDB:

Обычно MongoDB сжимает индексы во время регулярных обновлений. Для большинства пользователей команда reIndex не нужна. Однако, возможно, стоит запустить его, если размер коллекции значительно изменился или если индексы потребляют непропорционально большой объем дискового пространства.

У кого-то была необходимость запустить операцию восстановления индекса, которая того стоила?


person javierfdezg    schedule 20.05.2015    source источник
comment
Я просто использую его, если добавляю новый index.   -  person Erkan Demirel    schedule 20.05.2015
comment
Но если вы добавите новый индекс, он будет построен прямо тогда, вам не нужно переиндексировать   -  person javierfdezg    schedule 20.05.2015


Ответы (2)


Согласно документации MongoDB, обычно нет необходимости регулярно перестраивать индексы.

ПРИМЕЧАНИЕ. Любые советы по хранению становятся более интересными с MongoDB 3.0+, в котором введен API подключаемого механизма хранения. Мои комментарии ниже конкретно относятся к механизму хранения MMAP по умолчанию в MongoDB 3.0 и ранее. WiredTiger и другие механизмы хранения имеют разные реализации хранения данных и индексов.

Восстановление индекса с помощью механизма хранения MMAP может дать некоторые преимущества, если:

  • Индекс занимает больше места, чем ожидалось, по сравнению с данными. Примечание: вам необходимо отслеживать исторические данные и размер индекса, чтобы иметь базовый показатель для сравнения.

  • Вы хотите перейти со старого формата индекса на новый. Если рекомендуется переиндексировать, это будет упомянуто в примечаниях к обновлению. Например, в MongoDB 2.0 были внесены значительные улучшения производительности индекса. поэтому примечания к выпуску включают предлагаемую переиндексацию в формат v2.0 после обновления. Точно так же MongoDB 2.6 представила индексы 2dsphere (v2.0), которые имеют другое поведение по умолчанию (по умолчанию разреженное). Существующие индексы не перестраиваются после обновления версии индекса; выбор, когда и когда выполнять обновление, остается за администратором базы данных.

  • Вы изменили формат _id для коллекции с монотонно увеличивающегося ключа (например, ObjectID) на случайное значение или наоборот. Это немного эзотерично, но есть оптимизация индекса, которая разбивает сегменты b-дерева на 90/10 (вместо 50/50), если вы вставляете _id, которые всегда увеличиваются (ref: SERVER-983). Если характер ваших _ids значительно изменится, возможно, удастся построить более эффективное b-дерево с повторным индексированием.

Для получения дополнительной информации об общем поведении B-дерева см .: Википедия: B-дерево

Визуализация использования индекса

Если вам действительно интересно немного подробнее изучить внутреннее устройство индекса, вы можете попробовать несколько экспериментальных команд / инструментов. Я ожидаю, что они ограничены только MongoDB 2.4 и 2.6:

person Stennie    schedule 21.05.2015
comment
Я заметил странное поведение, когда я выбираю случайную запись из коллекции, иногда она возвращает пустой курсор. Как вы думаете, это проблема индексации? - person Charles Chow; 08.09.2018
comment
очевидно, неверно сформированный индекс вызвал проблему с нулевым возвратом документа {$ sample}, перестроение индекса устранило эту проблему - person Charles Chow; 08.09.2018
comment
@Stennie после выполнения createIndex для большой коллекции, следует ли мне запустить reIndex (), чтобы все существующие документы были проиндексированы? - person eran otzap; 07.07.2021
comment
@eranotzap Если индекс был создан, он включает все совпадающие документы, которые существуют или добавляются / обновляются в проиндексированной коллекции в будущем - вам не нужно регулярно переиндексировать. Я хотел бы отметить, что этот исходный вопрос и ответ относятся к 2015 году, когда MongoDB 3.0 была последней серией серверных версий. Концепции индексирования (и переиндексации) не изменились, но серверный продукт претерпел значительные изменения, и я хотел бы иметь это в виду при поиске информации для применения к современным версиям серверов. - person Stennie; 07.07.2021

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

Общая идея индекса

При переходе от одного документа к другому в полной коллекции документов есть много потраченного впустую времени и усилий, пропуская все данные, с которыми не нужно иметь дело. Если вы ищете документ с идентификатором «1234», необходимость перемещать более 100 КБ каждого документа замедляет его работу.

Вместо того, чтобы искать по всему содержимому каждого документа в коллекции (физическое перемещение считывающих головок диска и т. Д.), Индекс делает это быстро. По сути, это пара ключ / значение, которая дает вам идентификатор и местоположение этого документа. MongoDB может быстро просмотреть все идентификаторы в индексе, найти расположение необходимых документов и сразу загрузить их.

Назначение размера файла для индекса

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

Большинство операционных систем выделяют блоки дискового пространства определенными размерами блоков. Большинство баз данных также выделяют дисковое пространство большими частями по мере необходимости.

Вместо того, чтобы увеличивать размер файла на 100 КБ при добавлении 100 КБ документов, MongoDB, вероятно, вырастет на 1 МБ или, может быть, 10 МБ или что-то в этом роде - я не знаю, каков фактический размер роста. В SQL Server вы можете сказать, насколько быстро он растет, и в MongoDB, вероятно, есть что-то подобное.

Увеличение кусков дает возможность быстрее «наращивать» документы в пространстве, потому что база данных не нуждается в постоянном расширении. Если в базе данных уже выделено 10 МБ пространства, она может просто использовать это пространство. Нет необходимости постоянно расширять файл для каждого документа. Ему просто нужно записать данные в файл.

Вероятно, это верно в отношении коллекций и индексов для коллекций - всего, что хранится на диске.

Размер файла и перестройка индекса

Когда в большую коллекцию добавляется и удаляется много документов, индекс становится фрагментированным. Ключи индекса могут быть не в порядке, потому что было место в середине файла индекса, а не в конце, когда нужно было построить индекс. Между ключами индекса также может быть много места.

Если в индексе 10 000 элементов и необходимо вставить # 10 001, его можно вставить в середину файла индекса. Теперь индекс должен перестроиться, чтобы привести все в порядок. Это включает перемещение большого количества данных, чтобы освободить место в конце файла и поместить элемент № 10,001 в конец.

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

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

Восстановить для большого индексного файла

Чтобы правильно сжать индексный файл до разумного размера и все в порядке, может потребоваться много операций доступа к диску и операций ввода-вывода. Переместите предметы с места на временное место, освободите место в нужном месте, переместите их обратно. Кстати, чтобы освободить место, вам пришлось переместить другие предметы во временное место. Это рекурсивно и тяжеловесно.

Следовательно, если у вас очень большое количество элементов в коллекции и в эту коллекцию регулярно добавляются и удаляются элементы, может потребоваться перестроить индекс с нуля. Это приведет к стиранию текущего индексного файла и его перестройке с нуля, что, вероятно, будет быстрее, чем попытка выполнить тысячи перемещений внутри существующего файла. Вместо того, чтобы перемещать объекты, он просто записывает их последовательно, с нуля.

Большое изменение размера коллекции

Принимая во внимание все, о чем я предполагаю выше, большое изменение размера коллекции вызовет такого рода взбучку. Если у вас есть 10 000 документов в коллекции и вы удалите 8 000 из них ... ну, теперь у вас есть пустое место в вашем индексном файле, где раньше находились 8 000 элементов. MongoDB необходимо переместить оставшиеся 2000 элементов в физическом файле, чтобы восстановить его в компактной форме.

Вместо того, чтобы ждать, пока будут очищены 8000 пустых пространств, возможно, будет быстрее перестроить с нуля с оставшимися 2000 элементами.

Заключение? Может быть?

Итак, процитированная вами документация, вероятно, будет иметь дело с потребностями в «больших данных» или с коллекциями и индексами, требующими большого количества ресурсов.

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

Я предполагаю, что «большинство пользователей» в документации означает, что 99,9% или более коллекций mongodb не должны беспокоиться об этом.

Конкретный случай MongoDB

Согласно документации MongoDB:

Метод remove () не удаляет индексы

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

person Derick Bailey    schedule 20.05.2015
comment
К сожалению, в вашем описании индексов отсутствуют фундаментальные концепции, лежащие в основе структуры данных B-дерева и не совсем точно представляет, как работают индексы в MongoDB :). Ключи хранятся в сегментах, которые представляют диапазон значений ... вставка или удаление одного документа не требует перестройки индекса, это просто добавление ключей в соответствующее место структуры данных. В Википедии есть гораздо лучшее описание. Что касается команды remove(): она не удаляет определения индекса (но записи индекса действительно удаляются). - person Stennie; 21.05.2015