Немного о сфинксе, часть 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
Суммарный размер зависит от количества данных в источнике (таблице)
Если эти файлы есть, и в нужном кол-ве, можно приступать к написанию поиска. Об этом во второй части.
Так вот зачем sql_attr_str2ordinal нужен.
А если я буду искать по подстроке поля tov_name («велосипед» вместо «велосипед 'Кама'») — он найдёт что надо?
Павел
да найдет. по крайней мере у меня работает ))