Стоит ли разворачивать отдельный поисковый кластер, если у вас уже крутится PostgreSQL? Вопрос знаком каждому, кто хоть раз добавлял поисковую строку в веб-приложение. С одной стороны — зрелая реляционная база с встроенным полнотекстовым движком. С другой — Elasticsearch, созданный специально для того, чтобы искать быстро, много и умно.
В этой статье — не абстрактное «Elasticsearch быстрее», а чек-лист критериев, которые помогут принять решение именно для вашего проекта. Вы увидите, в каких сценариях PostgreSQL закрывает 80% задач поиска без лишней инфраструктуры, а где без отдельного поискового движка уже не обойтись.
Как PostgreSQL реализует полнотекстовый поиск
PostgreSQL умеет в полнотекстовый поиск «из коробки» и делает это гораздо серьёзнее, чем просто LIKE '%запрос%'. В основе лежат два специальных типа данных и один тип индекса.
tsvector — это уже разобранный и нормализованный документ. База берёт текст, разбивает на лексемы, выбрасывает стоп-слова и приводит слова к нормальной форме. Например, «машины быстро ехали» превращается в набор лексем 'машин':1 'быстр':2 'ех':3. Дальше поиск работает не по строкам, а по этим лексемам.
tsquery — это ваш поисковый запрос в том же представлении. Конструкция to_tsquery('russian', 'быстрая & машина') даст 'быстр' & 'машин'. Сравнение идёт через оператор @@: tsvector @@ tsquery. Именно тут происходит магия нечёткого совпадения без всякого pg_trgm.
Чтобы всё это работало быстро, используют GIN-индекс. Он строится по tsvector и позволяет находить документы за доли секунды даже в таблицах на сотни тысяч строк. Для ранжирования есть функции ts_rank и ts_rank_cd: они учитывают частоту слов, близость лексем в документе и отдают наиболее релевантные результаты первыми.
Отдельно стоит расширение pg_trgm. Оно не про лексемы, а про триграммы — комбинации из трёх подряд идущих символов. Благодаря ему работают запросы вроде LIKE '%подстрока%' и поиск похожих строк без знания точного слова. GIN-индекс по триграммам делает такой поиск очень шустрым, и это часто закрывает потребности в «живом» поиске и опечатках без привлечения Elasticsearch.
Когда PostgreSQL справляется сам
Одинокая база данных может быть разумным выбором, если поиск не ядро вашего продукта, а скорее удобная вспомогательная функция. Вы удивитесь, но таких проектов — большинство.
Поиск — вторичная фича
Вы делаете административную панель, внутренний портал, b2b-систему или небольшой интернет-магазин. Пользователи ищут товары, заказы или контакты, а основная логика — транзакции, отчёты, учёт. Здесь полнотекстовые возможности PostgreSQL без проблем переваривают типовые запросы «по названию», «по описанию» или «по комментарию».
Все данные уже живут в PostgreSQL
Главное преимущество — нет синхронизации между базой и поисковым движком. Никакой очереди в RabbitMQ, никаких ночных джоб, рассинхронов и задержек: вставили документ — он тут же доступен для поиска. Если поисковый индекс обновляется в той же транзакции, вы получаете честную согласованность данных, а это снимает головную боль у разработчиков.
Единая инфраструктура и нулевой дополнительный бюджет
Каждый новый сервис — это не только ресурсы процессора и памяти, но и мониторинг, бэкапы, апгрейды, настройка алертов. Оставляя только PostgreSQL, команда не распыляется. Для стартапов и небольших команд, где один-два человека отвечают за всё, отказ от ES даёт колоссальную экономию сил.
Умеренные объёмы и некритичный SLA по поиску
До сотен тысяч или единиц миллионов записей встроенный FTS обычно не проседает по скорости. Если пиковая нагрузка — десятки поисковых запросов в секунду, скорее всего, вам хватит и PostgreSQL. Точных цифр никто не даст без ваших данных и тестов, но практика показывает, что на таких масштабах вы вряд ли заметите разницу в отзывчивости.
Нечёткий поиск и базовая релевантность без фанатизма
Связка tsvector + GIN закрывает морфологию и поиск по точным словоформам, а pg_trgm добивает опечатки и поиск подстрок. Ранжирование через ts_rank выводит более-менее подходящие результаты вверх. Если вам не нужно игровое автодополнение на каждый ввод символа и хитрые скоринговые модели, PostgreSQL полностью справляется.
Когда Elasticsearch незаменим
Бывают проекты, где поиск — главный герой, а не эпизодическая роль. Вот какие сигналы однозначно указывают, что пора смотреть в сторону Elasticsearch.
Поиск — core-функция продукта
Маркетплейс, база знаний, документация, каталог товаров с кучей фильтров, система аналитики логов. Пользователь приходит именно искать, и малейшая задержка или нерелевантная выдача бьёт по бизнесу. Elasticsearch заточен под это на уровне архитектуры: распределённый движок, который ищет быстро даже по десяткам миллионов документов.
Горизонтальное масштабирование и высокие нагрузки
Elasticsearch изначально проектировался как кластер. Шардирование позволяет распилить индекс на несколько узлов, репликация — выжить при падении одного из серверов. При росте данных и запросов вы просто добавляете новые ноды, и производительность растёт почти линейно. PostgreSQL же в одиночку рано или поздно упрётся в ресурсы одного сервера, а вертикальное масштабирование стоит дорого и имеет предел.
Тонкая настройка релевантности
Стандартный алгоритм BM25, лежащий в основе Lucene и Elasticsearch, — это промышленный стандарт. Вы можете настраивать similarity отдельно для каждого поля, менять веса, задавать бустинг по свежести документа или популярности товара. В арсенале ES есть пользовательские анализаторы: вы сами решаете, как разбивать текст на токены, какие стоп-слова игнорировать, подключать ли синонимы. PostgreSQL даёт базовый контроль, но гибкость Lucene недостижима.
Фасеты, агрегации и умное автодополнение
В Elasticsearch поиск не живёт отдельно от аналитики. Вы получаете фасетные фильтры (количество товаров по бренду, цене, цвету) прямо из поискового запроса за один проход. Автодополнение и исправление опечаток работают на основе специальных типов данных (completion suggester, phrase suggester). В PostgreSQL такие штуки либо невозможны, либо требуют сложных самодельных костылей.
Высокая скорость индексации и поиска при больших объёмах
Когда поток данных непрерывен (логи, события, обновления товаров миллионами), время индексации становится критичным. Elasticsearch умеет поглощать их быстро и не деградировать при параллельном поиске. В PostgreSQL частые вставки с тяжёлыми GIN-индексами могут замедлить и запись, и чтение — придётся хитрить с отложенной индексацией, что опять возвращает нас к проблеме синхронизации.
Сравнительный чек-лист: PostgreSQL FTS или Elasticsearch
Не существует универсального правила «если больше N записей — бери ES». Решение всегда многокритериальное. Пройдитесь по этому списку и отметьте, что ближе к вашей реальности.
Объём данных и скорость роста
— PostgreSQL: сотни тысяч – единицы миллионов документов, рост плавный.
— Elasticsearch: десятки миллионов и выше, данные прилетают сплошным потоком.Поиск как бизнес-критичная функция
— PostgreSQL: поиск — «приятно иметь», основной сценарий — CRUD.
— Elasticsearch: поиск — лицо продукта, плохая выдача = потеря клиентов.Требования к релевантности
— PostgreSQL: достаточно ранжирования по частоте слов и близости лексем.
— Elasticsearch: нужен бустинг по полям, синонимы, кастомные анализаторы, учёт бизнес-показателей в скоре.Операционная сложность и бюджет команды
— PostgreSQL: команда небольшая, лишний кластер — обуза, администрирует один и тот же человек.
— Elasticsearch: есть выделенный DevOps или готовая облачная управляемая версия, бюджет на инфраструктуру не критичен.Необходимость продвинутых поисковых интерфейсов
— PostgreSQL: простой текстовый ввод и кнопка «найти».
— Elasticsearch: фасетные фильтры, мгновенное автодополнение, «люди также ищут», поиск по нескольким полям с разным весом.Транзакционные гарантии и согласованность
— PostgreSQL: железобетонная согласованность, поиск в той же транзакции, что и основная бизнес-логика.
— Elasticsearch: eventual consistency, задержка между вставкой и появлением в индексе от миллисекунд до секунд.
Когда галочек в левой колонке больше, можно смело оставаться на PostgreSQL. Когда перевес вправо — пора всерьёз проектировать внедрение Elasticsearch.
Часто задаваемые вопросы
Можно ли использовать PostgreSQL для поиска по 10 миллионам документов?
Можно, но с оговорками. Всё зависит от размера индекса, сложности запросов и количества одновременных поисков. Если нагрузка умеренная, а поиск не обязан отвечать за десяток миллисекунд, PostgreSQL может справиться. Однако при такой размерности обычно уже задумываются о специализированном движке — лучше провести нагрузочное тестирование на копии данных.
Что такое pg_trgm и когда его подключать?
Расширение pg_trgm добавляет поддержку триграмм — комбинаций из трёх подряд идущих символов. Оно позволяет быстро искать подстроки (LIKE '%текст%'), находить слова с опечатками и вычислять похожесть строк. Подключайте его, когда нужен нечёткий поиск, которого нет в стандартном tsvector, например, для автодополнения или поиска по частичному вводу.
Нужна ли платная лицензия для Elasticsearch?
Elasticsearch доступен под открытой лицензией, и базовый набор функций бесплатен. Платные подписки дают дополнительную безопасность, техническую поддержку и продвинутые инструменты мониторинга. Для промышленной эксплуатации многие компании выбирают платный вариант, но для тестов и небольших проектов бесплатной версии достаточно.
Если я уже использую PostgreSQL, зачем мне Elasticsearch?
Причин может быть несколько: нужна производительность поиска на порядок выше, чем может дать одна база; нужны сложные пользовательские сценарии вроде фасетов и интерактивного автодополнения; поиск становится ключевым элементом продукта, и его просадки напрямую влияют на доход. Если всё это не про вас — спокойно оставайтесь на PostgreSQL.
Есть ли в PostgreSQL аналоги фасетов?
Прямого аналога нет. Фасеты можно эмулировать с помощью отдельных запросов с GROUP BY и агрегациями, но это медленно и не всегда удобно, особенно при больших объёмах данных. Elasticsearch делает фасетный разрез прямо внутри поискового движка, совмещая полнотекстовый поиск и аналитику.
Какой индекс выбрать: GIN или GiST для полнотекстового поиска?
GIN — вариант по умолчанию для tsvector. Он быстрее при выборке, но медленнее строится и чуть более прожорлив по памяти. GiST, наоборот, может быть медленнее при поиске, зато быстрее обновляется и занимает меньше места. Для большинства случаев, где поиск читает гораздо чаще, чем пишет, GIN — лучший выбор. Если у вас очень интенсивная запись и терпимость к чуть более медленному поиску — смотрите в сторону GiST.
Заключение: нет серебряной пули
Выбор между PostgreSQL и Elasticsearch — это не битва технологий, а вопрос архитектурной осознанности. Если ваша система уже хранит данные в PostgreSQL и поиск не доминирует в пользовательских сценариях, вы сэкономите кучу ресурсов и нервов, используя встроенный FTS. Как только поиск становится главным действующим лицом, а требования к релевантности и масштабируемости уходят за горизонт одной машины, Elasticsearch перестаёт быть роскошью и превращается в необходимость.
Не принимайте решение на основе чужого опыта «потому что у гиков из блога завелось на миллионе записей». Сделайте прототип на своих данных, нагрузите его реалистичным трафиком и честно измерьте — хватает ли PostgreSQL прямо сейчас. Именно этот подход убережёт от преждевременного усложнения и подготовит почву для роста, когда он действительно потребуется.
Источники
- PostgreSQL(Full Text Search) vs ElasticSearch
- Full-text search engine with PostgreSQL (part 2): Postgres ...
- PostgreSQL Full Text Search vs Elasticsearch Comparison
- Full-Text Search in PostgreSQL: Is It Better Than Elasticsearch?
- Comparing Native Postgres, ElasticSearch, and pg_search ...
- Сравнение полнотекстового поиска PostgreSQL и Elasticsearch




.svg.webp)



