Главная > Заметки, Сделай сам, Статьи > Немного о сфинксе, часть 1

Немного о сфинксе, часть 1

Есть такая Приблуда для ускорения поиска — СФИНКС (SPHINX)
http://sphinxsearch.com

Это демон, который компилится и встраивается в PHP. Полезна, если у вас огромные базы данных, по которым надо вести поиск.
В Моем случае это был раздел аптек. Мучился я с этим сфинксом пару месяцев, но пока им занимался, понял некоторые его хитрости. Но об этом чуть позже, сейчас расскажу просто о его работе.

Будем считать что сфинкс у вас уже установлен и готов к работе.

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

Допустим структура таблицы товаров у нас следующая (good):

city, id, fid, gid, name, price
(город, ID, фирма, категория, название, цена)

Структура фирм (firm):

id, city, name, web, e_mail, manager, address, phone, wt, transport, cr_id
(ID, город, название, сайт, мыло, манагер, адрес, телефон, рабочее время, транспорт, район города)

Как видим, две таблицы, в товара[ 1 лимон записей, в фирмах, порядка 5000. Для слияния таблиц методом LEFT JOIN или перечислением таблиц, такие варианты будут не положительно сказываться на производительность запроса. по этому выход такой:

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

firm.name, firm.cr_id 

Два поля, Название фирмы и район. т.е. расширенный поиск у нас будет состоять из поиска по фирме и району где она обитает.

Алгоритм слияния:

1. на момент импорта данных в вашу БД готовим дополнительный кусок кода
2. добавляем в таблицу товаров дополнительные необходимые поля firmname, firm_cr_id
3. переносим данные согласно условию good.firmname = firm.name, good.firm_cr_id = firm.cr_id

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

Результатом получится запрос для индексации:

SELECT id, id as tovar_id, fid, name, name as tov_name, price, firm_cr_id, firmname, gid, city  FROM `good`


Далее согласно конфигу сфинкса и нашему запросу, делаем следующие настройки:

source items:location
{
	sql_query_pre 	= USE mydatabase
	sql_query	= SELECT id, id as tovar_id, fid, name, name as tov_name, price, firm_cr_id, firmname, gid, city  FROM `good`
	sql_attr_uint  	= tovar_id
	sql_attr_float 	= price_rub
	sql_attr_uint  	= firm_cr_id
	sql_attr_uint  	= fid
	sql_attr_uint  	= gid
	sql_attr_uint  	= old_fid
	sql_attr_uint  	= city
	sql_attr_str2ordinal = tov_name
}
index items:location
{
        source                  = items
        path                    = /var/data/sphinx/items
        morphology              = stem_enru
        min_word_len            = 3
}

Опишу тут название двух этих составляющих:

1. SOURCE — это источник, от куда брать данные для индекса и как их обработать, в данном случае по порядку, выбирается база данных, где лежат наши таблицы, выполняется запрос, и применяются атрибуты к полям индекса запроса:

sql_attr_uint — говорит, что поле числовое, и поиск по нему и сортировка будет вестись как по числовому полу INT И т.п. в MySQL
sql_attr_float — говорит само за себя, FLOAT
sql_attr_str2ordinal — интересный атрибут, он превращает текстовые поля запроса в порядковые номера этих текстов в индексе. Пример: Компьютерная мышь = 1, Джойстик = 2, Макароны яичные = 3, т.е. везде для уникальных название будет свой ID, это полезно делать сортировку по названию, т.к. других способов нет, да и работает оно быстрее в миллиард раз))

2. INDEX — ну тут мы говорим, сто делать индекс, на основании источника, кидать в директорию, по определенным правилам. Подробнее в описании сфинкса.

после этого, Нужно запустить пере индексацию индексов, вот небольшой скрипт запуска пере индексации:

#!/usr/local/bin/bash
CONFIG=/usr/local/etc/sphinx.conf
#killall -9 searchd
#/usr/local/bin/searchd
#killall -9 searchd
/usr/local/bin/indexer --config $CONFIG --rotate --all
#killall -9 searchd
#/usr/local/bin/searchd
#/usr/local/bin/searchd --config $CONFIG

После пере индексации, в директории /var/data/sphinx/ появятся файлы, примерно 8 штук, со следующими расширениями:

items.spa
items.spd
items.sph
items.spi
items.spk
items.spl
items.spm
items.spp

Суммарный размер зависит от количества данных в источнике (таблице)

Если эти файлы есть, и в нужном кол-ве, можно приступать к написанию поиска. Об этом во второй части.

Заметки, Сделай сам, Статьи ,

  1. 14 Окт 2009 из 12:03 | #1

    Так вот зачем sql_attr_str2ordinal нужен.

    А если я буду искать по подстроке поля tov_name («велосипед» вместо «велосипед 'Кама'») — он найдёт что надо?

  1. Трекбеков пока нет.