Загадки сфинкса: полнотекстовый поиск

Sphinx — система полнотекстового поиска, разработанная Андреем Аксеновым и распространяемая по лицензии GNU GPL. Отличительной особенностью является высокая скорость индексации и поиска, а также интеграция с существующими СУБД (MySQL, PostgreSQL, ...) и API для распространённых языков программирования (официально поддерживаются PHP, Python, Java).

Если вы используете Debian, тогда для установки Sphinx достаточно выполнить команду:

sudo apt-get install sphinxsearch

Конфигурационный файл называется:

/etc/sphinxsearch/sphinx.conf

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

  • Полный - индексируются все данные целиком (запускаем редко - раз в сутки)
  • Дельта - индексируется только малая часть данных, добавленных в течении дня (запускаем каждые 5-10 минут)

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

CREATE TABLE `sphinx_counter`
(
    `index_name` ENUM( 'mysource' ) NOT NULL,
    `last_id` INT NOT NULL
) ENGINE = InnoDB;

Добавим для нашего индекса запись, для дальнейшего обновления:

INSERT INTO `sphinx_counter`(`index_name`,`last_id`) VALUES ('mysource',0);

Отредактируем конфигурационный файл Sphinx (/etc/sphinxsearch/sphinx.conf) следующим образом: добавим источник для подключения к базе данных:

source dbconnect
{
  type = mysql
  sql_host = localhost
  sql_user = myuserf
  sql_pass = mypass
  sql_db = mydb
  sql_port = 3306
  sql_sock = /tmp/mysql.sock
}

Источник данных для полного индекса добавим как потомка dbconnect:

source full_data: dbconnect
{
  sql_query_pre = SET NAMES utf8
  sql_query_pre = SET CHARACTER SET utf8
  # обновляем наш счетчик
  sql_query_pre = update sphinx_counter \
                  set last_id = \
                 ( select max(ID) from data_table) \
                 where index_name = 'mysource';
  # выбираем все данные для полного-индекса
  sql_query = select id, data from data_table;
  sql_field_string = data
  sql_query_info = select id, data from data_table where id = $id
  sql_ranged_throttle = 0
}

Определим источник для дельта индекса:

source delta_data: dbconnect
{
  sql_query_pre = SET NAMES utf8
  sql_query_pre = SET CHARACTER SET utf8
  # выбираем все данные для дельта-индекса
  sql_query = select id, data from data_table where id > \
              ( SELECT last_id FROM sphinx_counter \
                WHERE index_name = 'mysource' );
  sql_field_string = data
  sql_query_info = select id, data from data_table where id = $id
  sql_ranged_throttle = 0
}

Определим полный индекс:

index full_index
{
  type = plain
  source = full_data
  path = /var/sphinxsearch/fulldata
  charset_type = utf-8
  preopen = 1
}

Строка text=plain означает, что используются стандартные индексные файлы Sphinx. Другие варианты: distributed(если есть индексные файлы, распределенные по нескольким узлам сети) и rt(что означает реального времени). Эти индексы можно изменять динамически. Строка source=full_dataсвязывает источник данных full_data с индексом. На самом деле можно объединить несколько источников данных в один индекс, но в данном примере это не делается. Строка path= определяет имя индексного файла и место его хранения. Строка charset_type= используемый набор символов. Наконец preopen=1 предписывает демону поиска открыть все индексные файлы после загрузки, не дожидаясь поступления первых запросов.

Определим дельта-индекс:

index delta_index : full_index
{
  source = delta_data
  path = /var/sphinxsearch/deltadata
}

Настроим индексатор:

indexer
{
  mem_limit = 1024M
}

mem_limit определяет объем памяти, который будет выделен индексатору. Теперь настроим поисковый демон:

searchd
{
  listen = 127.0.0.1:9306:mysql41
  log = /var/sphinxsearch/log/searchd.log
  query_log = /var/sphinxsearch/log/query.log
  read_timeout = 5
  max_children = 30
  pid_file = /var/run/searchd.pid
  max_matches = 1000
}

Определения searchd самоочевидны, за исключением listen=. Этот параметр можно использовать для указания того, по какому IP-адресу и порту обращаться к двоичному сетевому протоколу SphinxQL. Если нужно взаимодействовать с протоколом напрямую, можно использовать стандартный клиент MySQL, указав mysql -P 9306, и выполнять запросы, даже не запуская программу MySQL на своем компьютере.

Для автоматического перестроения индексов добавим следующие задания в cron:

0 1 * * *   /usr/bin/indexer --config /etc/sphinxsearch/sphinx.conf \
            full_index --rotate > /dev/null
*/5 * * * * /usr/bin/indexer --config /etc/sphinxsearch/sphinx.conf \
            delta_index --rotate > /dev/null

После построение индексов их можно использовать. Начиная с версии 0.9.9-rc2 Sphinx поддерживает бинарный протокол, используемый MySQL. В результате чего можно использовать MySQL CLI в качестве клиента для Sphinx. И наш поисковый запрос запишется следующим образом:

SELECT * FROM full_index WHERE MATCH('search');

 

27.09.2016









 
архив

подписка