Поиск в БД

advertisement
Sphinx и его применения
для поиска в БД
Андрей Аксенов
shodan@shodan.ru
Поиск в БД – зачем?
• Популярные СУБД недостаточно хорошо
справляются с задачей поиска (в широком
смысле)
• В частности, с полнотекстовым поиском
– Скорость поиска
– Скорость обновления таблицы
– Релевантность
• В некоторых случаях, есть проблемы даже
с “обычными” выборками
– Подробности во второй части доклада
Поиск в БД – как?
• Sphinx
– Система для организации полнотекстового
поиска
– Бесплатная
– Открытая (open-source, GPL)
– Изначально разработана для интеграции с БД
• О чем мы расскажем
– Краткий обзор внутреннего устройства
– Краткий обзор возможностей
– Краткий обзор практических применений
Sphinx. Общие сведения
• Две основных программы
– indexer, получает данные из источников (БД) и
строит полнотекстовый индекс
– searchd, отвечает на поисковые запросы при
помощи построенных indexer-ом индексов
• Набор API для разных языков
– Легковесные нативные клиенты к searchd
– PHP, Python, Ruby, Perl, Java…
• SphinxSE
– Встраиваемый в MySQL клиент
– Storage engine для MySQL 5.0.x и 5.1.x
Sphinx. Терминология
• Документы Sphinx аналогичны записям в
базе данных
– Документ это набор текстовых полей и
численных атрибутов плюс уникальный ID –
аналог строки в таблице БД
– Набор полей и атрибутов не меняется в
пределах индекса – аналог таблицы в БД
– По полям можно вести полнотекстовый поиск
– По атрибутам можно дополнительно
фильтровать, сортировать, группировать
результаты поиска
Sphinx. Установка и использование
• Установка
– ./configure && make && make install
– vi sphinx.conf
– ./indexer myindex
– ./searchd
• Использование
– include ( “sphinxapi.php” );
– $cl = new SphinxClient ();
– $res = new $cl->Query ( “test”, “myindex” );
Sphinx. Устройство индексов
• Полнотекстовые индексы хранятся в FS
• Имеют специально обученный формат
• Формат монолитный, обновление данных
производится построением “с нуля”
• Проблема, но далеко не смертельная
– Быстрая скорость индексации (4-8 MB/sec)
– Partitioning индексов для снижения lag
– Принципиально отсутствует фрагментация
индекса
– Атрибуты можно обновлять в реальном
времени
Чуть подробнее про partitioning
• В простейшем случае, делаем 2 индекса
для индексации одной и той же “таблицы”
– Редко обновляемый main, содержащий
основную массу данных
– Часто обновляемый delta, содержащий
обновления с момента последней индексации
delta
• Зачастую, схема идеально согласуется с
характером изменений данных
– Форумы, блоги, mail/news архивы…
Источники данных
• В общем случае “откуда угодно”
– Встроенные “драйвера” для MySQL, Postgres,
XML файлов специального формата
• Источники разного типа можно
комбинировать в одном индексе
• Данные для индексации поступают не из
таблицы, а из выборки
• Т.е. можно делать дополнительную
обработку в момент выборки – JOIN-ы,
выбирать любой поднабор полей, итд.
Sphinx. Спец-возможности
• Помимо “просто” полнотекстового поиска,
Sphinx умеет много гитик:
– Поиск и ранжирование с учетом позиций слов
и близости фраз
– Произвольные атрибуты, в том числе MVA
– Сортировка, фильтрация, группировка
– Выдержки с подсветкой ключевых слов
– Распределенный поиск
– Оптимизация “близких” запросов
– Географическое расстояние (geo-distance)…
Ранжирование с учетом фраз
• Типичный подход – ранжирование только
на основании статистики по словам
• На больших коллекциях или не очень
редких ключевых словах – работает плохо
• Основной фактор ранжирования Sphinx –
max длина совпадения части фразы
запроса с документом
• Точные цитаты ранжируются выше всего,
качество “в целом” субъективно лучше
• Место для роста – quorums, frequencies…
Поддержка атрибутов
• Произвольное количество численных
(либо 1-32 bit unsigned integer, либо float)
атрибутов
• Необходимы для эффективной (!)
фильтрации, сортировки, группировки
результатов поиска
• Иначе (при хранении в БД), уже при 10100K найденных документов получается
неприемлемо медленно
• Extern, Inline, MVA
Сортировка и фильтрация
• Сортировка
– По комбинации атрибутов (“@weight desc,
user_rank desc”)
– Всегда оптимизируется с учетом top-N
запрошенных документов
• Фильтрация
– До 10+ раз быстрее, чем на стороне БД
– 3 вида фильтров: 1) набор значений, 2)
диапазон значений, 3) geodistance
– Произвольное количество фильтров
– Exclude-фильтры
Группировка
• Бывает интересна агрегированная
информация о результатах поиска
• Для этого в Sphinx сделана группировка
• Важное отличие – может быть неточной!
– Исполняется в фиксированной памяти
– Между распределенными узлами передаются
только агрегатные значения
– На практике, можно аккуратной настройкой
добиться точных значений
• Зачастую, абсолютная точность не важна
• Можно выбирать лучший элемент в группе
Распределенный поиск
• Last but not least…
• Распределенные индексы позволяют
параллельно запускать поиск на
нескольких машинах
– Запустили удаленные запросы
– Последовательно обыскали локальные
индексы
– Считали все удаленные результаты
– Объединили их вместе и вернули клиенту
• Можно использовать для multi-core
Пример 1.1. “Просто” поиск
•
•
•
•
•
Mininova.org
Заменили MySQL FT slaves
300-500K rows, 300-500 MB, 4-5 M q/day
Индексируем префиксы, а не сами слова
Long query tail – top-N запросов в кэше на
стороне приложения (20-30% из кэша,
самый частый ~1-2%)
• 2 сервера с полными репликами индекса
• Loadavg (теперь) около 0.3-0.4
Пример 1.2. “Просто” поиск
•
•
•
•
•
•
Boardreader.com
1B rows, 1.5 TB, 700K-1M q/day
6 серверов, 4xCPU + 16 GB RAM + 0.5 TB
4 копии searchd вместо одной (startup, HA)
4 “обычных” HDD вместо RAID (быстрее!)
Активный partitioning по времени
– Отдельные индексы 1-week, 3-month, all-time
• Распределенное “горячее” обновление версии
– Критична обратная совместимость
– В любой момент отсутствует ~1/24 документов
Пример 2. “Обычные” выборки
•
•
•
•
Sahibinden.com
400K rows, 500M, 3M q/day
99 полей, проблема с MySQL индексами
Sphinx использован и для полнотекстовых
поисков, и “обычных” выборок
– Добавляется ряд keywords при индексации
– Оказалось быстрее и удобнее, чем MySQL…
– Частая быстрая переиндексация, 9-15 секунд
раз в 1 минуту на одном из 8+ CPUs
• PHP API overhead стал значимым
– Сделали 2 индекса, на 34 и 99 атрибутов
Пример 3. Группировка
• Boardreader.com
• Потребовались отчеты по ссылкам – top
доменов, на/с которых ссылались, и т.п.
• 150-200 Mrows, 50-100 GB data, 60-100 Kq
– Запросы строго с группировкой и сортировкой
по COUNT / COUNT DISTINCT
– Много входных rows (1-10 M), при этом
небольшой result set
– Абсолютная точность не требуется
• MySQL исполнял прототипы до 300 секунд
• Распараллелили при помощи Sphinx
Пример 3. Группировка (cont’d)
• Группировка на 6x4 CPU кластере
– Параллельно с другой нагрузкой
– Распределенно, быстро, почти точно
• Предобработка индексируемых данных
– UDF для выделения всех “интересных”
подстрок в отдельные “слова”
• Потребовались доработки
– COUNT DISTINCT
– 64-bit ids (из-за схемы нумерации и коллизий)
• Место для оптимизаций
– Поскольку релевантность не важна…
Пример 4. MVA выборки
•
•
•
•
•
Grouply.com
N миллионов сообщений, M тегов
Интересные применения для MVA
“Официальное” для фильтрации по тегам
Для экономии SQL выборок
– БД сильно раздроблена на несколько
физических серверов
– JOIN в общем случае… нелегок
– MVA для агрегации (в момент индексации),
хранения, возврата ряда значений
Выводы
• Sphinx, понятно, не панацея
• Однако, для довольно широкого круга
задач – неплохой выбор
• Кстати, ряд возможностей остался за
бортом доклада…
• Пробуйте!
• Заходите – http://sphinxsearch.com/
• Пишите – shodan@shodan.ru
Download