Инженерная команда сервиса видеохостинга заменила индекс SQLite FTS5 на кластер OpenSearch, что позволило снизить количество запросов с нулевым результатом с 12 % до 1,4 % и повысить показатель переходов из поиска (search-to-click) на 9 %, сохранив при этом задержку менее 28 мс.
Почему переход стал необходимым
Расширение для полнотекстового поиска SQLite (FTS5) выглядит привлекательно: оно хранится в том же файле, что и остальные данные, не требует лицензионных отчислений и мгновенно возвращает совпадения при точном соответствии токенов. Однако логи платформы показали, что около двенадцати процентов пользовательских поисковых запросов не возвращали никаких результатов. Основной причиной были опечатки, такие как «intersteller» или «avengrs endgame» — именно такие ошибки люди часто допускают при наборе на мобильных клавиатурах.
Быстрое решение с использованием триграмм (фрагментов из трех символов) снизило долю пустых поисковых запросов до 7 %, но создало две проблемы. Во-первых, размер индекса увеличился более чем в три раза по сравнению с исходным, что привело к росту затрат на хранение и замедлению обновлений. Во-вторых, пострадала релевантность: нечеткое соответствие (fuzzy matching) выдавало шумную смесь несвязанных видео, что путало пользователей вместо того, чтобы помогать им.
Команда пришла к выводу, что необходим специализированный поисковый движок с нативной устойчивостью к опечаткам и сложной системой оценки релевантности.
Построение конвейера OpenSearch
Использование SQLite в качестве первоисточника (source of truth)
OpenSearch служил временной репликой только для чтения. Все метаданные видео оставались в SQLite; поисковый индекс можно было перестроить без риска потери данных. Если кластер OpenSearch выходил из строя, приложение автоматически переключалось на исходный движок FTS5.
Многоуровневая релевантность с использованием оператора «should»
Вместо того чтобы полагаться только на нечеткое соответствие, запрос объединял три условия:
- Точное совпадение фразы — максимальный вес (boost), поощряющий пользователей, которые ввели название правильно.
- Наличие всех терминов — средний вес, отлавливающий запросы, где присутствуют все слова, но не обязательно в строгом порядке.
- Нечеткое соответствие (fuzzy match) — низкий вес, выступающее в роли страховки для запросов с опечатками.
Такая иерархия сохраняла точность для корректных запросов, обеспечивая при этом гибкий механизм обработки опечаток.
Настройка параметров нечеткого поиска
Установка длины префикса (prefix length) равной 1 заставляла первый символ каждого термина совпадать, прежде чем вступала в силу логика нечеткого поиска. Это правило обеспечивало высокую скорость поиска и предотвращало взрывной рост количества потенциальных вариантов, который может перегрузить память. Команда также ограничила максимальное количество расширений терминов (term expansions) — еще одна мера защиты от неконтролируемого потребления ресурсов.
Стратегия синхронизации
Три взаимодополняющих процесса поддерживают синхронизацию индекса OpenSearch с SQLite:
- Cron-задача для синхронизации новых данных.
- Еженощная проверка различий (diff pass) — сканирование на наличие несоответствий, которые могли пропустить инкрементальные обновления.
- Еженедельная полная пересборка — выполняется под псевдонимом индекса (index alias), после чего псевдоним переключается одной операцией, что гарантирует отсутствие простоев.
Измеримый результат через две недели
- Количество запросов с нулевым результатом снизилось с 12 % до 1,4 %.
- Конверсия из поиска в клик выросла на 9 %.
- Медианная задержка осталась ниже 28 мс, что полностью соответствует целевым показателям пользовательского опыта платформы.
Предостережения и нюансы
Миграция — это не просто обновление по принципу «подключил и забыл». Команда подчеркивает, что основная база данных никогда не должна заменяться поисковым движком; SQLite остается основным хранилищем всех метаданных видео.
Итог
Добавление устойчивости к опечаткам с помощью специализированного поискового движка превратило заметный тупик в пользовательском пути в плавный и быстрый процесс. Этот кейс показывает, что дисциплинированная архитектура — сохранение реляционного хранилища в качестве первоисточника, многоуровневая релевантность и защита логики нечеткого поиска — позволяет достичь измеримых преимуществ без ущерба для стабильности.