Простая настройка и запуск Sphinx на debian для полнотекстового поиска на сайте

Стандартный полнотекстовый поиск MySQL не решает многих задач и не настолько производителен, как поиск Sphinx. Привожу простой пример установки и настройки Sphinx в debian для организации поиска на сайтах. Установим версию 2.2.11 из стандартного репозитория: apt install sphinxsearch

Далее заходим /etc/sphinxsearch/sphinx.conf и настраиваем конфиг подобным образом:

#
# Minimal Sphinx configuration sample (clean, simple, functional)
#

source src_test_db
{
	type			= mysql

	sql_host		= localhost
	sql_user		= root
	sql_pass		=
	sql_db			= test_db
	sql_port		= 3306	# optional, default is 3306

	sql_query		= \
		SELECT id, category_id, UNIX_TIMESTAMP(date_created) AS date_created, text \
		FROM questions

	sql_attr_uint		= category_id
	sql_attr_timestamp	= date_created
	sql_field_string    = text
	sql_query_pre = SET CHARACTER_SET_RESULTS=utf8
    sql_query_pre = SET NAMES utf8
}


index index_test_db
{
	source			= src_test_db
	path			= /var/lib/sphinxsearch/data/index_test_db
	morphology      = stem_enru
	html_strip      = 1
	min_word_len    = 2
	min_infix_len   = 1
	index_exact_words = 1
	expand_keywords = 1
	charset_table = 0..9, A..Z->a..z, a..z, (, ), {, }, [, ], $, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+0435, U+451->U+0435, U+2A, U+2D, U+00AB, U+00D7
}


indexer
{
	mem_limit		= 256M
}


searchd
{
	listen			= 127.0.0.1:9806:mysql41
	log			= /var/lib/sphinxsearch/log/searchd.log
	query_log		= /var/lib/sphinxsearch/log/query.log
	read_timeout		= 5
	max_children		= 30
	pid_file		= /var/run/sphinxsearch/searchd.pid
	seamless_rotate		= 1
	preopen_indexes		= 1
	unlink_old		= 1
	workers			= threads # for RT to work
	binlog_path		= /var/lib/sphinxsearch/data
}

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

systemctl restart sphinxsearch
indexer --all --verbose

Индексация/переиндексация БД таблицы объемом 5 млн записей в 2.7 гига занимает чуть больше 2 минут. Скорость отменная. Чтобы поиск заработал необходимо запустить демон с соответствующим конфигом:

/usr/bin/searchd -c /etc/sphinxsearch/sphinx.conf

Теперь мы можем искать по индексу из консоли или из под php. Для поиска из консоли mysql -h0 -P9806 и собственно запрос:

SELECT *, SNIPPET(text, 'test search query') as `snippet`, WEIGHT() AS `w` FROM `index_test_db` WHERE MATCH('test search query') LIMIT 1000

Из под php соединяемся так: $db_index = new mysqli(‘localhost:9806’);  бд выбирать не нужно, сразу можно делать запросы, как в обычной базе. Только запросы делаются не к таблице, а к её индексу. Сервис слушает порт 9806 на локальной lo петле и протоколу SphinxQL. В примерах по данному протоколу обычно указывается порт 9306, но у меня он занят. Также в образцах конфигов данный порт зачем-то открыт для всех желающих извне… Хм… это 100% точно есть хорошо. Например, если в конфиге настроено обновление индексов в реальном времени, то это получается, можно с сервера дяди Васи «обновить» чего-нибудь кому-нибудь тому, кто не вдумчиво скопипастил конфиг? А  таких товарищей 99%, прям бери в гугл бей «9306:mysql41», находи где они постят свои проблемы со sphinx на форумах, определяй их серваки и в путь. Поэтому в конфиге обязательно 127.0.0.1:9806:mysql41 Слушает только локалка!

Для переиндексации необходимо выполнить:

indexer -c /etc/sphinxsearch/sphinx.conf --rotate <source_name>
indexer -c /etc/sphinxsearch/sphinx.conf --rotate --all
# После переиндексации killall searchd и снова запуск демона.
killall searchd
/usr/bin/searchd -c /etc/sphinxsearch/sphinx.conf

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

indexer -c /etc/sphinxsearch/sphinx.conf --rotate --all && killall searchd && sleep 1 && /usr/bin/searchd -c /etc/sphinxsearch/sphinx.conf

Но лучше сделать по другому. Демон нужно запускать при каждом перезапуске системы, поэтому создадим соответствующий unit файл, который будет это делать. И теперь наша крон задача на переиндексацию будет выглядеть так:

indexer -c /etc/sphinxsearch/sphinx.conf --rotate --all > /dev/null && systemctl restart runsearchd > /dev/null

12 комментариев

  1. Здравствуйте!
    1. Как осуществляется сортировка на уровне запроса к Spinhx.
    2. Почему максимум 1000 резултатов?
    3. Кажись что не всё индексируется, то есть — некоторые запросы не вазращают результат.

    Не помешала бы инструкция по Manticore — это что то вроде нового Spinhxsa.

    1. Здравствуйте! 1. Для каждого запроса расчитывается WEIGHT() это вес, релевантность. По ней и сортировка автоматически, как она там осуществляется это уже сам движок копать надо. 2. В старых версиях в конфиге был параметр max_matches, теперь это можно задавать в самом запросе через OPTION
      select * from index_tab where match(‘1’) limit 7898 OPTION max_matches=5000;
      Параметр влияет насколько я понимаю на производительность, чем он меньше, тем быстрее. 3. Зависит от настроек конфига, там масса параметров в директивах индексации.
      Manticore весьма интересный проект судя по всему, спасибо, буду иметь его ввиду на будущее.

  2. Не уверин что ограничение 1000 не баг данной версии… Так-же не плохо этокое руководство по обновлению 2.11 на более новые версии Shinks, которые вроде как есть. Спасибо!

    1. А что там руководить по обновлению, вот сейчас Sphinx 3.4.1 самый новый, он вообще установки, сборки не требует, скачал и в локальном каталоге любом развернуть можно. Каталоги под индексы и все данные какие угодно можно ставить. Конечно старые индексы наверное лучше не юзать, новые в другом каталоге создать. Демон старый останавливаем потом, новый с новым конфигом запускаем и вперед. Или если запуск searchd демона в автозагрузке служба прописана, как у меня на примере тут есть, тогда там меняем путь на новый конфиг файл и новый searchd демон. Там вся работа по обновлению вообще сводится тупо к работе с каталогами, что куда, да и всё. У меня единственно в директивах индексации параметр sql_attr_timestamp(удаленв новых версиях) на sql_attr_uint заменить пришлось и всё. Да и ротацию логов в наверное нужно ещё прописать в /etc/logrotate.d/sphinxsearch, вот не помню что там с ними, я это прописывал или установщик ранее, ну например:

      /var/log/sphinxsearch/*.log {
      daily
      rotate 4
      compress
      missingok
      sharedscripts
      postrotate
      start-stop-daemon -K -p /var/run/sphinxsearch/searchd.pid -s USR1 -x /usr/bin/searchd -q
      endscript
      }

      И для индексации из mysql нужны драйвера
      apt-get install libmysqlclient-dev libpq-dev unixodbc-dev
      apt-get install libmariadb-client-lgpl-dev-compat

      1. Так оно для Вас дело-то пластиковое… Для меня это очень мутно. Вы поймите, что ‘чайникам’ хорошо — когда есть пошаговые инструкции. Тогда каждый чайник может себя(хоть на миг) почувствовать профессионалом… Я думаю, что нюансов то там куча… к примеру я понятии не имею как это «скачал и в локальном каталоге любом развернуть» Я понимаю что это не запуск шаттла, но полагаю, что Ваш сайт юзают и чайники… 🤣👍 так им то и хорошо — коды всё по полочкам. К примеру — вот нафига мне новая версия Sphinx? Да потому что на этой sphinxApi не работает на php7. 😉😆 Ну то есть — я немогу сделать высвечивания, livesearch…
        Спасибо!

          1. Спасибо Вам. Скажите своё мнение — как по функционалу и быстродействию Вы оцениваете работу 3 и 2 версии Sphinx? То есть — есть лил смысл переписывать APi для 2версии?

          2. Я особо разницы не вижу, в бд по 10-20 млн. записей, ищет и тот и этот быстро. Был затык из-за всевозможных предлогов и междометий, долго длился поиск, это нагружало сервак, причем директивы конфигруции не помогали по таймауту и т.п. и в запросе опцию прописывал, есть такая максимальное время запроса. Только стоп лист помог. Даже скрипт написал для его автообновления https://github.com/avtobys/sphinx-stopwords-updater чтобы треш исключить этот. Анализирует логи за несколько дней, собирает самые длительные запросы и вычленяет слова которые привели к их тормозам. Возможно в 3 это пофиксили, не знаю, не экспериментировал.

          3. Еще вопросик, есть ли в2 или 3. версие наработки по livesearch чтобы применить его с ‘коробки’? Иле это нужно полностью достраивать?
            Спасибо!

          4. Нет, это уже javascript, если фронтенд имеете ввиду. Тут кому что нужно уже, индивидуально. А если php, ну вот например https://github.com/avtobys/sphinx-3.4.1/blob/master/api/test.php кидаете запросы и получаете json ответы. Единственное, рекомендовал бы не кидать запрос сразу по событию ввода, а делать 300-400 мс таймаут, ожидая нажатия следующей клавиши, и либо отменять предыдущий таймаут, либо отправлять запрос. Визуально это будет не заметно, поиск как был «на лету», так и будет, но поможет избежать лишних запросов, когда либо быстро набирают текст, либо, что ещё хуже зажимают backspace — на каждый стертый символ идет событие и получается куча ненужных запросов.

          5.     function search(q) {
                    $.getJSON("/api.php?q=" + q).done(function (res) {
                        // разбираем json и делаем свою логику с DOM
                    });
                }
            
                let tID;
                $(document).on("input onkeyup", "input#search", function () { // событие нажатия/ввода
                    clearTimeout(tID); // отменяем таймаут предыдущее событие
                    let q = this.value.trim();
                    tID = setTimeout(function () { // задаем таймаут
                        search(q); // отправляем запрос на бекенд
                    }, 350);
                });
          6. Вроде понятно — буду пробовать реализовать на 2версие. А там кто знает… :) Конечно это была бы хорошей новой темой для Вас типа ‘ реализация live search на Sphinx’ Спасибо!

Добавить комментарий для avtobys Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *