Обзорный доклад про базовое внутреннее устройство любого современного поискового движка. Про сжатые списки документов и позиций, как затем с ними работает поиск совпадающих документов (и разные операторы), как устроено ранжирование найденных документов, как бывают устроены и работают с фильтрацией и агрегацией дополнительные (нетекстовые) атрибуты документов. По возможности, упоминание всех известных вариантов реализаций (как, вообще, можно, как сделано в Sphinx, как в Lucene).
2. Поиск устроен вот так
• Сначала индексация
• Потом поиск
• Ставить, конечно, Sphinx +
мегаконтракт на поддержку
• Всё, расходимся
3. Поиск устроен вот так
• Индексация
– Берем документы
– Извлекаем ключевые слова
– Строим спецструктуру, FT index
• Поиск
– Берем запрос, ищем по спецструктуре
– Допобработка (where/order/group,
кластер, реранжирование, …)
4. Данные решают все
• FT index =
– Словарь
– Списки документов
– Списки позиций
– Формат хранения этого всего
6. Данные решают все
• Элемент словаря на самом деле =
– Слово
– Указатель на документы/позиции
• Или инлайн данные
– Дополнительная метаинформация
• Или никакой
– Например,
w=“Абыр”, docoff=1234, posoff=5678,
ndocs=12, nposs=72, fieldmask=3, …
7. Данные решают все
• Словарь =
– Обычно сортированный вектор
• Круто хеш, но прощай, поиск подстрок
– Обычно пожат
• Абыр, Абырр, Абыррр, Абырвалг!
– Эффективно с инлайнигом
• Зачем ndocs=1 docsoff=1234, если можно
сразу docid=9876?!
– Оп, и вот сразу детали ретализации
8. Данные решают все
• Документы и позиции
– Всегда сортированы (иначе не пересечь)
Васечкин => [ 7, 40, 42, 1917, … ]
Вася => [ 3, 141, 592, 653, … ]
– Обычно пожаты (отдельная поднаука)
– Хранятся и отдельно и вперемешку
– Плюс спецфокусы! (Маски полей,
битмапы, плоская нумерация, итд итп)
10. The fuck we care?!
• СКОРОСТЬ блин (и объем еще)
• Например,
“что” => [1,3,4,5,6,10,11,…]
varint => [1,2,1,1,1,4, 1,…] x 8 bit
gvi/pfd => [0,1,0,0,0,3, 0,…] x 0..2 bit
• Про 0 bit тащемта не шутка!(Хотя
такое щщасье случается оч редко)
11. Текста мало, дайте цифер
• Еще есть атрибуты
• Бывают schemaful, schemaless
• Хранить можно как угодно, все знают
– “relational”, JSON text, BSON, …
• Lucene = ФлексиТормоз!!!
– По меньшей мере, была и по дефолту
• Sphinx = АдскаяСмесь!!!
– relational + SphinxBSON
12. А к цифрам - еще цифер!!!
• Атрибуты можно хранить
– Тупо
– Менее тупо
• Со схемой: построчно, колоночно
• Без схемы: K-V, иерархия, сжатие
• Индексы: никаких, эмуляция, родные
13. А что еще (м.Строгино!!!)
• Про ранжирование
• Про сегменты и весь реалтайм
• Про еще отличия физики S vs L
• Про разницу подходов к снаряду
• Про как бенчить надо, а как будут
• Про жопки в реализациях
– Как зажигал [abc*]
• Плюс должно быть слово КЛАСТЕР
14. Про ранжирование
• Если не нужно, ура, булев матчинг
• Если лёгкое, BM25 (у нас +proximity)
• Простая формула, ДВЕ переменные
– TF, IDF по словам; плюс avg_doc_length
• Если тяжёлое, всё весело
– Например, 20 переменных. Или 800.
15. Про сегменты и весь RT
• Как устроен т.н. “реалтайм”?
(здесь короче картинка такая с лысым
писюном из Матрицы и типа гнутой
ложкой - ну хоть не дырявой, бггг)
• Его нету, есть create/merge/purge
• Sphinx еще умеет update атрибутивки
16. И еще про разную физику
• Sphinx vs Lucene чота волнует всех
• Концептуально все одинаково, но
• Разные форматы индекса, атрибутов
• S = общие словари, L = по полям
• S = таблица атрибутов в памяти,
L = документы на диске и кешкешкеш
• S = микс schemaful/less, L = вроде
только less
17. Про подходы к снаряду
– (плюс детали реализации, ага)
• S = надо все уметь быстро считать
• L = надо уметь отдавать из кеша!!!
• S = позиции, фикс RAM, итд итп
• L = ненене, булев и BM25 и кеш/RAM
• S = плохо, хрен включишь кеш
• L = плохо, хрен сделаешь бенчмарк
• Внезапно история про Xapian!!!
18. Про жопки в реализации
• Здесь внезапная история про [abc*] и
про старые версии – СЕГОДНЯ ВЕЗДЕ
ВСЕ НОРМАЛЬНО
• Старый Lucene жог, full scan словаря
• Старый Sphinx жог, безлимитный
expansion и “везде мелкие” буфера
19. Про как надо бенчить
• На оценку 3 = разные системы,
одинаковый запрос, смотрим время
• На оценку 4 = повторяем запрос N
раз, считаем среднее время, чтобы
кеш прогрело и не дрожало
• На оценку 5 = выкидываем 1й прогон
всегда и даже выкидываем outliers,
считаем среднее без них
20.
21. Тёплое != мягкое
• Где ошибка?
• “берем разные системы, делаем к
ним одинаковый запрос”…
• Одинаковый запрос
•ОДИНАКОВЫЙ
ЗАПРОС, КАРЛ!
22. Marketing driven defaults 1
• Sphinx = типа быстрое strict-AND, зато
medium rare proximity+bm15
ранжирование
• Lucene = типа медленное OR, зато
lightweight bm25 ранжирование
• Xapian!!!
• …и это еще цветочки!!!
23. Marketing driven defaults 2
• Повторные запросы?
• Sphinx (*) = честно вычисляем всё
заново, кешируется только дисковое
чтение, и то у OS
• Lucene = на всех уровнях есть
внутренние кеши, некоторые
невозможно отключить никак
24. Marketing driven defaults 3
• Сниппеты, прям шедевр!
• “А чё у вас в N раз медленнее, чем
Solr?”
– Поддержка синтаксиса VS bag-of-words
– Произвольный текст VS только
преиндексированный
– И ключевая “оптимизация” про 64KB!