Дельта индекс в Sphinx

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

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

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

Схема дельта индексов

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

Схема такого индекса называется main+delta. Рассмотрим на примере:

Данные

Пусть у нас есть таблица с очень простой структурой:
CREATE TABLE  `test`.`articles` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `text` text,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
Ее и будем индексировать. Для начала ее нужно заполнить данными. Можно воспользоваться вот этим скриптом:
mysql_connect('localhost', 'root', 'root');
mysql_select_db('test');

$text = "Название XVII века, дано по Кисловской слободе. Кислошниками называли людей, профессионально занимавшихся засолкой и квашением овощей и ягод, приготовлением кислых напитков — кваса, щей и др. В районе нынешних Кисловских переулков находилась принадлежавшая двору царицы царицына Кисловская слобода.";

$words = explode(' ', $text);
mysql_query('set names utf8');

for ( $i = 1; $i < 10000; $i ++ )
{
	shuffle($words);
	mysql_query('INSERT INTO articles SET `text` = \'' . mysql_real_escape_string(implode(' ', $words)) . "'");
	echo '.';
}
Этот скрипт добавит 10000 рядков со случайным набором слов.

Основной индекс

При перестройке основного индекса, нам понадобиться знать ID последней проиндексированной статьи, для этого создадим еще одну таблицу в MySQL:
CREATE TABLE sph_counter
(
    counter_id INTEGER PRIMARY KEY NOT NULL,
    max_doc_id INTEGER NOT NULL
);
Теперь в конфигурационном файле (spinx.conf) обьявим параметры основного индекса:
source main
{
	# ... - тут идет тип и параметры доступа в СУБД

	sql_query_pre		= SET NAMES utf8
	sql_query_pre 		= REPLACE INTO sph_counter SELECT 1, MAX(id) FROM articles
	sql_query		= SELECT id, text FROM articles
	sql_query_info		= SELECT * FROM articles WHERE id=$id
}

index main
{
	source			= main
	path			= /var/data/articles.main
}
В таблицу sph_counter будет записываться ID последней проиндексированной статьи (в основном индексе). Этот индекс следует запускать редко (все зависит от времени реиндексации, но обычно основной индекс перестраивают ночью, в минимумы нагрузки).

Дельта индекс

Для построения дельта индекса будем использовать данные из таблицы sph_counter, что-бы узнать, начиная с какой записи строить индекс. Конфигурация будет следующая:
source delta : main
{
	sql_query_pre = SET NAMES utf8
	sql_query = \
		SELECT id, text FROM articles \
		WHERE id > ( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
}

index delta : main
{
    source = delta
    path = /var/data/articles.delta
}
Как видно из конфигурации мы добавили дополнительный индекс. Запрос на выборку данных составлен начиная с последнего проиндексированного документа из основного индекса.

Поиск

Теперь пересторим главный и дельта индекс, а также запустим демон поиска:
indexer --all
searchd
При поиске, необходимо указать, какие индексы использовать:
...
$cl->Query ( "век", "main delta" );
После этого, можно добавить несколько рядков в таблицу и перестроить только дельта индекс:
indexer --rotate delta
Новый запрос поиска сразу отразит актуальное состояние таблицы. Т.к. дельта индекс работает очень быстро, следует перестраивать его довольно часто (раз в 5...15 минут). Основной индекс можно также не перестраивать, а сливать с дельта индексом (merge), но об этом в другой раз.

А Вы пользуетесь дельта индексами?

Подпишитесь на Хайлоад с помощью Google аккаунта
или закройте эту хрень