АрхитектураПроектирование системАрхитектор программных систем

Когда для поиска по каталогу оправдана отдельная поисковая система вместо запросов к основной базе?

Когда для поиска по каталогу оправдана отдельная поисковая система вместо запросов к основной базе?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Отдельная поисковая система оправдана, когда требования к поиску заметно сложнее возможностей основной базы: нужны полнотекстовый поиск, релевантность, исправление опечаток, фасеты, сложное ранжирование или высокая поисковая нагрузка. Основная база при этом остаётся источником истины, а поисковый индекс — производной моделью для чтения.

Если поиск сводится к точным фильтрам по небольшому числу полей, а объём и нагрузка умеренны, отдельная система обычно неоправданна: она добавляет стоимость эксплуатации, задержку обновления и риск рассинхронизации.

Исторический контекст

Реляционные базы данных хорошо решают задачи транзакционного хранения: гарантируют целостность, поддерживают связи и выполняют точные условия выборки. Однако полнотекстовый поиск и ранжирование требуют специализированных структур, например обратного индекса, анализа слов и оценки релевантности.

Поэтому в системах с развитым поиском появились отдельные поисковые движки. Они оптимизированы для чтения и поиска по индексам, но обычно не заменяют транзакционную базу как надёжное хранилище состояния.

Постановка проблемы

Каталог может содержать миллионы товаров, текстовые описания, синонимы, опечатки, фильтры и сортировку по нескольким критериям. Выполнение таких запросов непосредственно в основной базе может привести к росту нагрузки, нестабильной задержке и конкуренции поиска с операциями изменения товаров и заказов.

Однако вынесение поиска в отдельную систему не является бесплатной оптимизацией. Индекс нужно строить, обновлять, мониторить и восстанавливать, а изменения в основной базе и поисковом индексе могут быть видны не одновременно.

Подробное решение

Сначала разделяют требования. Точные фильтры, простая сортировка и поиск по индексируемым полям обычно остаются в основной базе. Полнотекстовый поиск, морфология, исправление опечаток, подсказки, фасетная навигация и сложное ранжирование являются аргументами в пользу поискового индекса.

Основная база хранит каноническое состояние товара. При изменении товара система публикует событие или иным способом передаёт изменение в индексатор, который обновляет поисковый индекс. Такая схема обычно обеспечивает eventual consistency: пользователь может кратковременно увидеть в результатах старую цену или название.

Чтобы снизить риск рассинхронизации, обновление индекса делают повторяемым, применяют очередь с повторной доставкой, контролируют отставание индекса и предусматривают периодическую сверку с источником истины. Нельзя считать успешную запись только в индекс достаточным подтверждением сохранения товара.

Результаты поиска обычно содержат идентификаторы товаров и поисковые признаки. Актуальные данные, критичные для пользователя, можно дополнительно получать из основной базы или проверять перед оформлением заказа. Это увеличивает число чтений и задержку, но не позволяет устаревшему индексу стать источником цены, остатка или права на покупку.

Главные компромиссы таковы:

  • Плюсы: более выразительный поиск, независимое масштабирование чтения, специализированное ранжирование и снижение нагрузки на транзакционную базу.
  • Минусы: дополнительная инфраструктура, стоимость хранения индекса, сложность обновления и временная несогласованность.
  • Ограничение: поисковый индекс не должен единолично определять критичные бизнес-решения, если его данные могут устареть.

Решение следует принимать не по объёму каталога самому по себе, а по сочетанию требований к функциональности поиска, задержке, числу запросов, допустимой несвежести и операционной зрелости команды.

Ситуация из практики

Интернет-магазин хранил каталог в реляционной базе. Сначала поиск выполнялся по нескольким точным атрибутам и работал в основной базе без проблем. После появления поиска по описаниям, синонимам и фасетам запросы стали занимать непредсказуемое время и конкурировать с обновлением остатков.

Рассматривались три варианта. Оптимизация запросов и добавление индексов были простыми, но не решали полнотекстовое ранжирование и увеличивали стоимость записи. Полное копирование каталога в поисковую систему давало нужную функциональность, но требовало обработки ошибок и контроля задержки индекса. Отказ от сложного поиска снижал техническую сложность, но ухудшал пользовательский сценарий.

Выбрали отдельный поисковый индекс, обновляемый из событий изменения каталога. В индекс помещали поисковые поля и идентификаторы товаров, а цену и остаток проверяли из актуального источника перед добавлением товара в корзину и оформлением заказа. Это сохранило расширенный поиск, изолировало его нагрузку и не позволило устаревшему индексу принять решение о продаже.

Что кандидаты часто упускают

  1. Должен ли поисковый индекс быть транзакционно согласован с основной базой?

Обычно строгая синхронность не требуется для результатов поиска, если бизнес допускает небольшую задержку появления изменений. Важнее явно определить допустимое время отставания и не использовать индекс для критичных проверок, таких как наличие товара, цена при списании или права доступа.

Если же изменение должно быть видно в поиске немедленно, это усложняет архитектуру: потребуется синхронное обновление или механизм подтверждения готовности индекса. Такой выбор увеличивает задержку записи и связывает доступность основной базы с доступностью поисковой системы.

  1. Почему нельзя просто считать поисковую систему второй основной базой?

Поисковый индекс строится под чтение и может иметь другую модель данных, задержку обновления и неполные поля. При ошибке индекса, потере данных или некорректной переиндексации его можно восстановить из источника истины.

Если сделать индекс единственным хранилищем, восстановление и проверка корректности становятся значительно сложнее, а поисковая система начинает отвечать за транзакционные гарантии, для которых она не предназначена в данной архитектуре. Разделение ролей упрощает контроль целостности.

  1. Как определить, что отдельная поисковая система уже не оправдывает свою сложность?

Нужно сравнить не только среднюю задержку запросов, но и требования к поисковой функциональности, хвостовые задержки, пиковую нагрузку, стоимость эксплуатации и допустимую несвежесть данных. Если основной базе хватает обычных индексов, запросы предсказуемы, а команда не нуждается в полнотекстовом ранжировании, отдельный движок создаст больше рисков, чем пользы.

Решение стоит проверять нагрузочным тестом и прототипом поисковых сценариев. Критерием является выполнение измеримых требований при приемлемой операционной стоимости, а не сам факт наличия большого каталога.