Как и в других системах баз данных, в ArangoDB можно использовать индексы для ускорения запросов на поиск данных, иногда на много порядков. Правильная настройка индексов необходима для хорошей производительности запросов, поэтому это важная тема, затрагивающая большинство установок ArangoDB.

Это часть I о том, как индексы используются ArangoDB, где мы обсуждаем, какие типы индексов доступны в базе данных. Во второй части мы углубимся в то, как на самом деле добавлять индексы в модель данных и ускорять определенные запросы.

Этот пост в блоге относится к версиям ArangoDB 3.2 и 3.3.

Знакомство с различными типами индексов

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

Первичный индекс

Каждая коллекция, созданная в ArangoDB, будет иметь как минимум так называемый первичный индекс. Первичный индекс создается автоматически при создании коллекции, его нельзя ни удалить, ни изменить, ни создать явно. Основная обязанность индекса — индексировать значения атрибута _key коллекции и убедиться, что ключи документа в коллекции действительно уникальны.

Первичный индекс будет использоваться для поиска по атрибуту _key или _id коллекции, но только для запросов поиска на равенство. Вот несколько примеров запросов, которые будут использовать первичный индекс:

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

Внутреннее представление первичного индекса зависит от механизма хранения:

  • Для механизма хранения MMFiles основным индексом является индекс в памяти. Поиски в первичном индексе будут иметь амортизированную сложность O(1) для движка MMFiles, что означает, что этот индекс здесь очень эффективен.
  • Для механизма хранения RocksDB первичный индекс представляет собой внутренний отсортированный индекс на диске, поэтому его производительность будет хуже, чем у O(1).

Краевой индекс

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

Индекс будет использоваться запросами, выполняющими поиск по _from или _to. Несколько примеров запросов, которые будут использовать индекс ребра коллекции ребер:

Опять же, этот тип индекса будет использоваться только для поиска на равенство, но не для запросов диапазона. И снова внутреннее представление граничного индекса зависит от используемого механизма хранения:

  • Для механизма хранения MMFiles пограничный индекс является индексом в памяти. Таким образом, поиск в пограничном индексе движка MMFiles очень эффективен.
  • Для механизма хранения RocksDB краевой индекс представляет собой отсортированный индекс на диске, но перед ним будет автоматический хеш-кэш, который будет кэшировать документы, связанные с каждым краем в памяти. Поэтому он должен быть относительно эффективным после начального прогрева кэша.

В движке RocksDB пограничный индекс также можно использовать для сортировки по _from или _to для определенных типов запросов.

Хэш-индекс

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

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

Для механизма MMFiles хеш-индекс — это фактический хэш-индекс в памяти, который перестраивается в памяти из данных на диске при (повторной) загрузке коллекции. Поскольку это хеш-индекс, запрос должен выполнять поиск на равенство для всех атрибутов индекса, чтобы использовать индекс. Поиск диапазона не поддерживается для хеш-индекса MMFiles и не может использоваться для сортировки.

При создании индекса для нескольких атрибутов запрос должен выполнять поиск на равенство для всех атрибутов индекса, чтобы использовать этот индекс.

В следующих примерах предполагается, что для атрибутов country и zip присутствует индекс:

Следующие запросы не будут использовать этот хэш-индекс с механизмом MMFiles, поскольку они не запрашивают оба атрибута индекса на равенство.

В движке RocksDB внутренний хеш-индекс снова представляет собой отсортированный индекс на диске. Индекс имени «хэш» был сохранен здесь в основном из соображений совместимости. Хэш-индекс в RocksDB будет использоваться для запросов, выполняющих поиск на равенство атрибутов индекса, если либо все атрибуты индекса охватываются запросом, либо крайний левый префикс атрибутов индекса охватывается запросом. Последний использованный атрибут индекса в крайнем левом префиксе также может использоваться для поиска диапазона
.

Все следующие запросы будут использовать хэш-индекс для атрибутов country и zip (в этом порядке порядок атрибутов индексов будет иметь значение) с движком RocksDB:

Следующие запросы не будут использовать хеш-индекс для country и zip (в таком порядке) с движком RocksDB:

Хэш-индекс также можно использовать для сортировки атрибутов индекса с помощью механизма RocksDB при условии, что в предложении SORT используется одно и то же направление (либо все по возрастанию, либо все по убыванию) для всех атрибутов индекса. Опять же, индекс будет поддерживать сортировку по крайнему левому префиксу атрибутов индекса:

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

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

Пример:

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

Список пропусков

В движке MMFiles индекс списка пропуска фактически использует список пропуска в памяти за кулисами. Список пропуска — это отсортированная структура данных, поэтому индекс списка пропуска — это тип индекса общего назначения, который можно использовать для поддержки множества различных типов запросов (поиск равенства, сканирование диапазона, сортировка).

В движке RocksDB индекс списка пропуска использует ту же реализацию, что и хэш-индекс, поэтому все примечания о хеш-индексе на основе RocksDB применимы и к индексу списка пропуска на основе RocksDB. Опять же, название «skiplist» было сохранено только из соображений совместимости.

Независимо от базового механизма хранения индекс списка пропуска будет использоваться для запросов, выполняющих поиск на равенство атрибутов индекса, если либо все атрибуты индекса покрываются запросом, либо крайний левый префикс атрибутов индекса покрывается запросом. . Последний использованный атрибут индекса в крайнем левом префиксе также может использоваться для поиска диапазона.

Все следующие запросы будут использовать индекс списка пропуска для атрибутов country и zip (в этом порядке порядок атрибутов индекса имеет значение):

Следующие запросы не будут использовать индекс списка пропуска для country и zip (в этом порядке) с движком RocksDB:

Индекс списка пропуска также можно использовать для сортировки по атрибуту(ам) индекса при условии, что в предложении SORT используется одно и то же направление (либо все по возрастанию, либо все по убыванию) для всех атрибутов индекса. Опять же, индекс будет поддерживать сортировку по крайнему левому префиксу атрибутов индекса:

Полнотекстовый индекс

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

Полнотекстовый индекс используется только в запросах, использующих функцию AQL FULLTEXT.

При наличии полнотекстового индекса для атрибута text следующий запрос будет использовать этот полнотекстовый индекс для поиска всех документов, содержащих слово bart:

В настоящее время мы работаем над ArangoSearch (входит в состав ArangoDB 3.4), который станет превосходной заменой существующему полнотекстовому индексу. Он предлагает рейтинг релевантности, позволяет индексировать несколько атрибутов и поддерживает несколько языков (включая китайский и русский). Вы уже можете попробовать его, загрузив 3.4 Milestone и пройдя Учебное пособие по ArangoSearch.

Географический индекс

Географический индекс в ArangoDB будет хранить географические координаты из настраиваемого атрибута местоположения документов и может использоваться для эффективного поиска всех документов, ближайших к определенной географической координате. Кроме того, он поддерживает запрос документов, расположение которых находится в круге вокруг определенной географической координаты.

Исторически геоиндекс использовался только в запросах, использующих функции AQL NEAR (подробнее) и WITHIN (подробнее).

В более новых версиях ArangoDB (включая 3.3) он также будет использоваться для запросов, которые фильтруют расстояние между географической координатой, покрываемой индексом, и какой-либо другой координатой.

Например, следующий запрос будет использовать географический индекс для атрибутов latitude и longitude (в таком порядке):

Географический индекс также можно использовать для эффективного поиска документов, расположение которых ближе всего к определенной географической координате:

Обратите внимание, что порядок сортировки здесь должен быть возрастающим, чтобы можно было использовать индекс порядка. Подобные запросы наиболее эффективны, если предоставленное значение LIMIT довольно низкое.

В настоящее время мы работаем над значительным расширением и улучшением функциональности геоиндекса в ArangoDB 3.4. Он будет предлагать более продвинутые функции запросов, оптимизацию производительности и поддержку стандартных типов GeoJSON (многоугольники, мультиполигоны, полилинии, пересечения и т. д.).

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

Как ранее публиковалось на ArangoDB