Мы помогаем нашим клиентам не просто сделать сайт, а стать счастливее.
Ваше счастье находится всего в одном шаге: напишите нам.

Sphinx является распределенной поисковой системы для полнотекстового поиска. MySQL имеет собственный механизм хранения (MyISAM) для полнотекстового поиска, но его не так легко масштабировать. Sphinx имеет много других преимуществ, таких как:

  • высокая скорости индексации и поиска;
  • великолепная релевантность поиска;
  • и самое главное лучшую масштабируемость.

Сфинкс состоит из двух частей:

  • indexer - предназначен для извлечения информации и создания индекса.
  • searchd - необходим для обслуживания поисковых запросов и поиска в индексе созданого индексатором.

Устанавливаем необходимые для сборки Sphinx пакеты (что бы Sphinx собрался с поддержкой MySQL), набрав в консоли:

apt-get install libmysql++-dev

Скачиваем Sphinx во временную директорию, набрав в консоли:

cd /tmp
sudo wget http://sphinxsearch.com/files/sphinx-2.0.8-release.tar.gz

Распаковываем, набрав в консоли:

sudo tar -xzf sphinx-2.0.8-release.tar.gz

Собераем и устанавливаем, указывая что установить надо в /usr/local/sphinx и с поддержкой MySQL, набрав в консоли:

cd sphinx-2.0.8-release
sudo ./configure --prefix=/usr/local/sphinx --with-mysql
sudo make
sudo make install

Удалим уже не нужные файлы, набрав в консоли:

cd /tmp
sudo rm -r /tmp/sphinx-2.0.8-release
sudo rm /tmp/sphinx-2.0.8-release.tar.gz

Создадим базу данных в MySQL с именем sphinx и заполним её следующими данными:

DROP TABLE IF EXISTS sphinx.documents;

CREATE TABLE sphinx.documents
(
	id			INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
	group_id	INTEGER NOT NULL,
	group_id2	INTEGER NOT NULL,
	date_added	DATETIME NOT NULL,
	title		VARCHAR(255) NOT NULL,
	content		TEXT NOT NULL
);

INSERT INTO sphinx.documents ( id, group_id, group_id2, date_added, title, content ) VALUES
	( 1, 1, 5, NOW(), 'test one', 'this is my test document number one. also checking search within phrases.' ),
	( 2, 1, 6, NOW(), 'test two', 'this is my test document number two' ),
	( 3, 2, 7, NOW(), 'another doc', 'this is another group' ),
	( 4, 2, 8, NOW(), 'doc number four', 'this is to test groups' );

DROP TABLE IF EXISTS sphinx.tags;

CREATE TABLE sphinx.tags
(
	docid INTEGER NOT NULL,
	tagid INTEGER NOT NULL,
	UNIQUE(docid,tagid)
);

INSERT INTO sphinx.tags VALUES
	(1,1), (1,3), (1,5), (1,7),
	(2,6), (2,4), (2,2),
	(3,15),
	(4,7), (4,40);

Создадим файл с настройками /usr/local/sphinx/etc/sphinx.conf:

# Базовые настройки источника данных - информация о подключении к БД.
# В MySQL лучше всего создать отдельного пользователя и дать ему права на чтение только необходимых таблиц.
source baseSource 
{
  type     = mysql
  sql_host = 127.0.0.1  
  sql_user = mysql_user
  sql_pass = mysql_pass
  sql_db   = sphinx
  sql_port = 3306  
  
  # Используем сжатие при обмене данными с MySQL.
  mysql_connect_flags = 32 

  # Включам нужную кодировку соединения и выключаем кеш запросов.
  sql_query_pre = SET NAMES utf8
  sql_query_pre = SET SESSION query_cache_type=OFF
}

# Реальный источник данных, который берёт информацию о подключении к БД из baseSource.
# Содержит информацию как выбирать данные.
source nodeSource : baseSource 
{
  # Запрос на выборку данных.
  sql_query = SELECT doc.id, doc.title, group_id, doc.content, UNIX_TIMESTAMP(doc.date_added) AS date_added  FROM documents doc WHERE id>=$start AND id<=$end
  
  # Дробления получения данных на неколько итераций.
  sql_query_range = SELECT MIN(id),MAX(id) FROM documents
  # Сколько получать объектов за итерацию.
  sql_range_step = 1000
  
  # Описываем аттрибуты.
  sql_attr_timestamp	= date_added
  sql_attr_uint		    = group_id
}

# Настройки хранения индекса.
index nodeIndex
{
  source  = nodeSource
  path    = /usr/local/sphinx/var/data/nodeSource
  docinfo = extern

  mlock = 0

  # Используемые морфологические движки.
  morphology = stem_enru
  
  min_word_len = 1

  # Кодировака данных из источника.        
  charset_type  = utf-8
  charset_table = 0..9, A..Z->a..z, _, a..z, U+0401->U+0435, U+0451->U+0435, U+410..U+42F->U+430..U+44F, U+430..U+44F

  # Вырезаем из данных HTML-код.
  html_strip = 1
}

# Настройки индексатора.
indexer
{
  mem_limit = 32M
}

# Настройка демона-поисковика.
searchd
{
  listen            = 9306:mysql41
  log               = /usr/local/sphinx/var/log/searchd.log
  query_log         = /usr/local/sphinx/var/log/query.log
  query_log_format  = sphinxql
  read_timeout      = 5
  max_children      = 30
  pid_file          = /usr/local/sphinx/var/log/searchd.pid
  max_matches       = 100000
  seamless_rotate   = 1
  preopen_indexes   = 1
  unlink_old        = 1
  workers           = threads
  client_timeout    = 300 
  mva_updates_pool  = 1M 
  max_packet_size   = 8M 
  max_filters       = 256
  max_filter_values = 4096
  max_batch_queries = 32
}

Запустим индексатор для первоначального создания индекса, набрав в консоли:

 sudo /usr/local/sphinx/bin/indexer --all

Создадим скрипт запуска и остановки Sphinx /etc/init.d/sphinx:

#! /bin/sh

PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/local/sphinx/bin/searchd
NAME=sphinx
DESC=sphinx

#test -x $DAEMON || exit 0

case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile /usr/local/sphinx/var/log/searchd.pid --exec $DAEMON -- -c /usr/local/sphinx/etc/sphinx.conf || true
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /usr/local/sphinx/var/log/searchd.pid --exec $DAEMON || true
echo "$NAME."
;;
restart)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile /usr/local/sphinx/var/log/searchd.pid --exec $DAEMON -- -c /usr/local/sphinx/etc/sphinx.conf || true
sleep 1
start-stop-daemon --start --quiet --pidfile /usr/local/sphinx/var/log/searchd.pid --exec $DAEMON -- -c /usr/local/sphinx/etc/sphinx.conf || true
echo "$NAME."
;;
*)
echo "Usage: $NAME {start|stop|restart}" >&2
exit 1
;;
esac

exit 0

Сделаем его исполняемым и добавим в автостарт, набрав в консоли:

 chmod +x /etc/init.d/sphinx
update-rc.d sphinx defaults

Добавим перестроение поискового индекса по крону в файле /etc/cron.d/sphinx:

*/12 * * * * root /usr/local/sphinx/bin/indexer --rotate nodeIndex > /dev/null 2>&1

Перезапустим крон, набрав в консоли:

/etc/init.d/cron restart