perf(db): миграция 0079 — pg_trgm GIN-индексы поиска и горячие индексы

Шаг 0.11 плана production-готовности:
- триграммные GIN на tasks.title/description (ilike '%…%' без смены семантики)
- tasks(organization_id, updated_at DESC), tasks(form_id, updated_at)
- field_history(task_id), users(email)

Проверено на 100k задач: Seq Scan 77.5ms → Bitmap Index Scan 4.8ms (~16x)
This commit is contained in:
2026-09-07 21:09:50 +03:00
parent cf6f937108
commit a54ec775dd
4 changed files with 51 additions and 1 deletions

View File

@@ -0,0 +1,19 @@
-- Шаг 0.11 плана production-готовности: индексы для горячих путей.
-- pg_trgm — trusted extension (PostgreSQL 13+), создаётся владельцем БД без суперпользователя.
CREATE EXTENSION IF NOT EXISTS pg_trgm;
-- Ускорение подстрокового поиска задач (ilike '%…%') без смены семантики:
-- инвариант — поиск обязан находить совпадения внутри слов («омент» → «моментально»),
-- поэтому триграммные GIN-индексы, а НЕ tsvector.
CREATE INDEX IF NOT EXISTS tasks_title_trgm_idx ON tasks USING gin (title gin_trgm_ops);
CREATE INDEX IF NOT EXISTS tasks_description_trgm_idx ON tasks USING gin (description gin_trgm_ops);
-- Дельта-синхронизация (WHERE updated_at >= since) и сортировки по обновлению.
CREATE INDEX IF NOT EXISTS tasks_org_updated_idx ON tasks (organization_id, updated_at DESC);
CREATE INDEX IF NOT EXISTS tasks_form_updated_idx ON tasks (form_id, updated_at);
-- История полей по задаче (карточка задачи, аудит).
CREATE INDEX IF NOT EXISTS field_history_task_id_idx ON field_history (task_id);
-- Поиск пользователя по email (логин, приглашения, DaData-подбор).
CREATE INDEX IF NOT EXISTS users_email_idx ON users (email);