220 likes | 676 Vues
Sphinx и его применения для поиска в БД. Андрей Аксенов shodan@shodan.ru. Поиск в БД – зачем?. Популярные СУБД недостаточно хорошо справляются с задачей поиска ( в широком смысле ) В частности , с полнотекстовым поиском Скорость поиска Скорость обновления таблицы Релевантность
E N D
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) атрибутов • Необходимы для эффективной (!) фильтрации, сортировки, группировки результатов поиска • Иначе (при хранении в БД), уже при 10-100K найденных документов получается неприемлемо медленно • 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