Sphinx. Для чего нужны дельта-индексы и как их готовить?
Дельта индексы необходимы для того, чтобы не индексировать базу полностью в течении короткого времени, а использовать маленький индекс.
К примеру, мы имеем очень много записей в базе данных, сотни тысяч или несколько миллионов записей, и данные поступают очень часто, нам их необходимо индексировать, однако запускать каждые 5-10 минут индексацию - это слишком трудоемко.
Поэтому мы делаем два индекса:
- Полный - индексируются все данные целиком (запускаем раз в сутки)
- Дельта - индексируется только малая часть данных, добавленных в течении дня (запускаем каждые 5-10 минут)
Но как определять с какого момента индексировать данные в дельта-индексе?
Нам необходимо помнить крайний проиндексированный ид-записи из полного-индекса, и начинать индексировать данные только с него, все очень просто :)
Для этого создадим еще одну таблицу в базе данных, чтобы хранить там ид крайней записи из полного-индекса:
CREATE TABLE `sphinx_delta_counter` ( `index_name` ENUM( 'pyha_forum' ) NOT NULL, `last_post_id` INT UNSIGNED NOT NULL ) ENGINE = InnoDB;
Где,
- "index_name" - имя индекса, например если у вас много индексов с разных таблиц (можно опустить, если у вас один индекс);
- "last_post_id" - крайний номер записи для конкретного индекса.
Вставим для нашего индекса запись, чтобы потом можно было обновлять счетчик:
INSERT INTO `sphinx_delta_counter` SET `index_name` = 'pyha_forum', `last_post_id` = 0;
Вы конечно можете этот запрос и в индексе сфинкса использовать, предварительно переписав его на "on duplicate key" и добавив уникальный индекс на связку "index_name+last_post_id", однако я думаю это излишне.
Строим индексы в Sphinx
Привожу примерный конфигурационный файл, на примере предыдущей статьи /2009/smf-sphinx/.
# сорс для подключения к БД, далее его будем наследовать в других сорсах source dbconnect { type = mysql sql_host = localhost sql_user = pyha sql_pass = sql_db = pyha sql_port = 3306 sql_sock = /tmp/mysql.sock } # сорс полного-индекса source pyha_forum : dbconnect { sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 # обновляем наш счетчик, добавляем туда крайний ид записи для дельта-индекса sql_query_pre = \ update sphinx_delta_counter \ set last_post_id = (select max(ID_MSG) from smf_messages) \ where index_name = 'pyha_forum'; # выбираем все данные для полного-индекса sql_query = \ select ID_MSG, concat('user:',posterName) as posterName, subject, body \ from smf_messages; sql_query_info = select ID_MSG, posterName, subject, body from smf_messages where ID_MSG = $id sql_ranged_throttle = 0 } # сорс дельта-индекса source pyha_forum_delta : dbconnect { sql_query_pre = SET NAMES utf8 sql_query_pre = SET CHARACTER SET utf8 # выбираем только те данные, которые появились после проиндексации полного-индекса sql_query = \ select ID_MSG, concat('user:',posterName) as posterName, subject, body \ from smf_messages \ where ID_MSG > (select last_post_id from sphinx_delta_counter where index_name = 'pyha_forum'); sql_query_info = select ID_MSG, posterName, subject, body from smf_messages where ID_MSG = $id sql_ranged_throttle = 0 } # полный-индекс index pyha_forum { source = pyha_forum path = /var/sphinxsearch/pyha_forum docinfo = extern mlock = 0 morphology = stem_enru min_word_len = 2 charset_type = utf-8 charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F min_infix_len = 2 enable_star = 1 } # дельта-индекс index pyha_forum_delta : pyha_forum { source = pyha_forum_delta path = /var/sphinxsearch/pyha_forum_delta } # настройки индексатора indexer { mem_limit = 32M } # настройки поискового демона searchd { address = 127.0.0.1 port = 3312 log = /var/sphinxsearch/log/searchd.log query_log = /var/sphinxsearch/log/query.log read_timeout = 5 max_children = 30 #pid_file = /var/sphinxsearch/log/searchd.pid max_matches = 1000 }
Ну вот и все, сфинкс настроен, далее поставим переиндексацию в крон.
Ставим в крон
0 1 * * * /usr/local/bin/indexer --config /usr/local/etc/sphinx.conf.sh pyha_forum --rotate > /dev/null */5 * * * * /usr/local/bin/indexer --config /usr/local/etc/sphinx.conf.sh pyha_forum_delta --rotate > /dev/null
Где,
- Индексировать полный-индекс каждый день в час ночи
- Индексировать дельта-индекс каждые пять минут
Не понятно что за конфиг "/usr/local/etc/sphinx.conf.sh"?
Тогда, читаем статью Инклуд конфигов Sphinx.
Добавим поиск по дельта-индексу в код
Так как я использую SphinxSE, то добавить надо так:
`query` = "поисковый запрос;index=pyha_forum,pyha_forum_delta"
Тогда будет производится поиск по полному- и дельта-индексам!
Встраиваем в SMF
Далее, раз мы разбираем пример на основе статьи /2009/smf-sphinx/, то снова найдем код в "/Source/Search.php" (строка ~1377):
$request = db_query( "SELECT `sm`.`ID_TOPIC`, `ssm`.`id` AS `ID_MSG`, 1000 AS `relevance`, 0 AS `num_matches` FROM `sphinx_smf_messages` AS `ssm` LEFT JOIN `smf_messages` AS `sm` ON `ssm`.`id` = `sm`.`ID_MSG` WHERE `ssm`.`query` = '".$context['search_params']['search'].";weights=1,2,3' LIMIT " . (int) $_REQUEST['start'] . ", $modSettings[search_results_per_page]", __FILE__, __LINE__);
заменим на
$request = db_query( "SELECT `sm`.`ID_TOPIC`, `ssm`.`id` AS `ID_MSG`, 1000 AS `relevance`, 0 AS `num_matches` FROM `sphinx_smf_messages` AS `ssm` LEFT JOIN `smf_messages` AS `sm` ON `ssm`.`id` = `sm`.`ID_MSG` WHERE `ssm`.`query` = '".$context['search_params']['search'].";weights=1,2,3;index=pyha_forum,pyha_forum_delta' LIMIT " . (int) $_REQUEST['start'] . ", $modSettings[search_results_per_page]", __FILE__, __LINE__);
Ну вот и все :)
Комментарии
Что вы так боитесь использовать слово последний? суеверия =)
Я служил в Военно-Морской Авиации, там слово "последний" - нет, потомучто "последний вылет". Вот там из меня и выбили это слово ;)
а ларчик просто открывался.. Спасибо за информацию))
удобно проиндексировать только часть страницы, которая тебе нужна и на выходе получить максимальный результат
Хочу посоветоваться. Есть ли смысл создавать дельта индексы, если полная индексация системы происходит примерно за 3-4 минуты?
думаю нет, по крайней мере я бы не заморачивался...
хотя если вам надо индексировать каждую минуту, то можно подумать о дельте...
У вас ротейт идет 3-4 минуты?
Доброе время суток, я вот делал по такому алгоритму строю дельта индекс, там появились новые индексы, потом добавляю их в основной индекс с помощью --merge , в принципе все отлично, но хотел бы Вас спросить можно ли как то удалять индексы из дельта индекса после слияния в основной ? заранее всех благодарю!
Спасибо разобрался! :)
Elvis, как решили?
Разве счётчик нада обновлять не в сорсе дельта индекса ?
Grind, а на основании чего вы так решили?
Предпологал, что после каждой дельта индексации происходит изменение индекса, для последующей индексации от этого id.
А вот после индексации основного-индекса запоминается максимальный проиндексированный ид, и с него начинает дельта-индекс индексировать данные
Осилил не на 100%, у меня вопрос: как поступать с отредактированными постами. Получается недостаточно знать id "крайнего" сообщения, не лучше ли вместо него использовать таймстамп последнего редактировани?
Да, можно и так, главное сделать выборку в БД данных которые тебе нужны.
зы. сейчас есть real-time индексы
Доброе время суток.
Работаю со Sphinx 2.0.1-beta на Win7 SP1.
В процессе приготовления дельта-индексов возникли вопросы:
1. Ошибка при переиндексации
Смотрим в searchd.log:
[WARNING: rotating index 'ix_name': rename 'C:../ix_name.spd' to 'C:../ix_name.old.spd' failed: Broken pipe]
[WARNING: rotating index 'ix_name': rename to .old failed; using old index]
[rotating finished]
Рещение: sphinx.conf.in => searchd settings => preopen_indexes = 0 (defualt - 1)
2. Параметр seamless_rotate (default - 1)
После переиндексации смотрим в searchd.log:
[rotating indices (seamless=0)]
[rotating index 'ix_name': success]
[rotating finished]
Обнаруживаем что seamless=0, но ведь по умолчанию seamless_rotate=1!
Решение: sphinx.conf.in => searchd settings => seamless_rotate = 1
Прошу прокомментировать если что-то нет так.
Интересно бы узнать назначение preopen_indexes, а так же как лучше обновлять главный индекс: перестроением(--rotate) или слиянием главного с дельтой (--merge)
Оставьте свой комментарий