Основы индексов Manticore

В этой статье мы обсуждаем введение в индексы Manticore.

Manticore Search поддерживает два типа индексов:

  • простой (или офлайн или дисковый) индекс. Данные индексируются один раз при создании, он поддерживает онлайн перестройку и онлайн обновления для не текстовых атрибутов

  • индекс RealTime. Подобно таблице базы данных, онлайн обновления возможны в любое время

Кроме того, специальный индекс на основе типа RealTime, называемый percolate, может использоваться для хранения <span class="std std-ref">Перколяционных запросов</span> .

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

  • первая колонка всегда является беззнаковым 64-битным ненулевым числом, называемым id. В отличие от базы данных, нет механизма автоинкремента, поэтому необходимо убедиться, что идентификаторы документов уникальны

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

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

Следующие типы данных могут храниться в атрибутах:

  • беззнаковые 32-битные и знаковые 64-битные целые числа

  • 32-битные числа с плавающей точкой одинарной точности

  • временные метки UNIX

  • логические значения

  • строки

  • JSON-объекты

  • многоцелевой список атрибутов беззнаковых 32-битных или знаковых 64-битных целых чисел

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

Другой тип индекса без хранения - это шаблон . Шаблонный индекс не хранит данных, но может содержать настройки токенизации, как индекс с хранением. Он может использоваться для тестирования правил токенизации или для генерации выделений.

Простые индексы


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

Производительность индексации зависит от нескольких факторов:

  • как быстро источник может предоставлять данные

  • настройки токенизации

  • ресурсы аппаратного обеспечения (мощность ЦП, скорость хранения)

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

Это подразумевает:

  • индекс не так свеж, как данные из источника

  • продолжительность индексации растет с объемом данных

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

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

Это можно сделать либо повторной индексацией основного индекса, либо объединением дельты с основным. Схема индекса main+delta подробно описана в <span class="std std-ref">Обновления дельта индекса</span> .

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

Для этого есть опция, позволяющая определить список идентификаторов документов, которые подавляются дельта индексом. Для получения дополнительных деталей смотрите <span class="std std-ref">sql_query_killlist</span> .

Индексы реального времени


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

Индекс RealTime начинается пустым, и вы можете добавлять, заменять, обновлять или удалять данные так же, как в таблице базы данных. Обновления сначала хранятся в зоне памяти (называемой RAM chunk), определяемой <span class="std std-ref">rt_mem_limit</span> . Когда это заполнено, оно сбрасывается как диск чанк - который по структуре подобен простому индексу. По мере увеличения числа дисковых чанков производительность поиска уменьшается, так как поиск выполняется последовательно по чанкам. Чтобы преодолеть это, чанки необходимо объединить в один, что делается с помощью команды <span class="std std-ref">OPTIMIZE INDEX</span> .
The RAM chunk can be also be force to discard on disk with FLUSH RAMCHUNK . Лучшие показатели производительности RT индекса достигаются после сброса RAM chunk и оптимизации индекса - RT индекс будет содержать все данные в одном фрагменте и будет иметь ту же производительность, что и обычный индекс.
Populating a RealTime can be done in two ways: firing INSERTs или конвертируя обычный индекс в RealTime. Существующие данные могут быть вставлены по одной записи за раз или большими партиями в одну вставку. Несколько параллельных работников, которые вставляют данные, ускорят процесс, но будет использовано больше ЦП.
Размер RAM chunk влияет на скорость обновлений, больший RAM chunk обеспечит лучшую производительность, но его нужно подбирать в зависимости от доступной памяти. Также стоит отметить, что rt_mem_limit ограничивает только размер RAM chunk. Дисковые фрагменты (которые практически являются обычным индексом) будут иметь свои собственные требования к памяти (для загрузки словаря или атрибутов).
Содержимое RAM chunk записывается на диск во время безопасного завершения работы или периодически, что определяется директивой rt_flush_period (это можно заставить сделать с помощью команды FLUSH RTINDEX). RT индекс также может использовать бинарное ведение журнала для записи изменений. Binlog может быть воспроизведен при запуске демона для восстановления после некорректного завершения работы и очищается после сброса RAM chunk на диск.
Стратегия сброса binlog strategy (аналогично innodb_flush_log_at_trx_commit в MySQL) может влиять на производительность. Binlog также можно отключить (установив пустой путь к binlog), но это оставляет без защиты обновления, которые еще не были сброшены на диск.
Local distributed indexes


A distributed index in Manticore Search doesn’t hold any data. Вместо этого он действует как «главный узел», чтобы запустить требуемый запрос на других индексах и предоставить объединенные результаты из ответов, которые он получает от узловых индексов. Распределенный индекс может подключаться к локальным индексам или индексам, расположенным на других серверах. В нашем случае распределенный индекс будет выглядеть так:

index_dist {
  type = distributed
  local = index1
  local = index2
  ...
 }

The last step to enable multi-core searches is to define dist_threads in searchd section. Dist_threads говорит движку максимальное количество потоков, которые он может использовать для распределенного индекса.

Remote distributed indexes and high availability



index mydist {
          type = distributed
          agent = box1:9312:shard1
          agent = box2:9312:shard2
          agent = box3:9312:shard3
          agent = box4:9312:shard4
}

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

index mydist {
          type = distributed
          agent = box1:9312|box5:9312:shard1
          agent = box2:9312:|box6:9312:shard2
          agent = box3:9312:|box7:9312:shard3
          agent = box4:9312:|box8:9312:shard4
}

Теперь мы добавили зеркала, каждый шард находится на 2 серверах. По умолчанию главный (экземпляр searchd с распределенным индексом) будет случайным образом выбирать одно из зеркал.

Режим, используемый для выбора зеркал, может быть установлен с помощью ha_strategy. В дополнение к случайному, еще одним простым методом является выбор по кругу (ha_strategy= roundrobin).

Более интересные стратегии основаны на вероятностях с учетом задержки. noerrors и nodeads не только удаляют зеркала с проблемами, но также мониторят время ответа и выполняют балансировку. Если зеркало отвечает медленнее (например, из-за выполнения некоторых операций на нем), оно будет получать меньше запросов. Когда зеркало восстанавливается и предоставляет лучшее время, оно будет получать больше запросов.

Установить Manticore Search

Установить Manticore Search