Индексы
Тема дорожной карты · PostgreSQL
Индексы — вспомогательные структуры данных в PostgreSQL, позволяющие движку реляционной базы данных находить строки, удовлетворяющие предикату запроса, без полного сканирования таблицы; индексирование является единственным наиболее эффективным инструментом оптимизации запросов. PostgreSQL поддерживает несколько типов индексов — B-tree (по умолчанию), Hash, GIN, GiST, SP-GiST и BRIN, — каждый из которых подходит для разных распределений данных и шаблонов запросов; все они создаются командой CREATE INDEX [CONCURRENTLY] ON table USING method (column). Параметр CONCURRENTLY строит индекс без удержания блокировки, препятствующей записям, что обязательно при добавлении индексов к таблицам в работающей продуктивной реляционной базе данных. Эффективная стратегия индексирования в PostgreSQL предполагает чтение вывода EXPLAIN ANALYZE для подтверждения использования индексов, анализ pg_stat_user_indexes для выявления неиспользуемых индексов, увеличивающих накладные расходы на INSERT/UPDATE, а также понимание частичных индексов (CREATE INDEX ON orders (id) WHERE status = 'pending') и индексов по выражениям (CREATE INDEX ON users (LOWER(email))) для более точечной оптимизации запросов.
Как это работает
Индексы ускоряют чтение ценой записи + storage. Типы Postgres: B-tree (дефолт, равенство + диапазон), Hash (только равенство), GIN (full-text, JSONB, containment массивов), GiST (геометрия, full-text), BRIN (огромные таблицы с естественным порядком — time-series), Bloom (multi-column равенство). Partial indexes (WHERE) пропускают нерелевантные строки; expression indexes ((lower(email))) ловят запрос с трансформацией; covering indexes (INCLUDE) избегают heap-lookup (index-only scans).
Когда применять
Индексируйте колонки в WHERE / JOIN / ORDER BY для запросов, которые реально гоняете — никогда "на всякий случай". EXPLAIN (ANALYZE, BUFFERS) — подтвердить, что индекс используется. Для JSONB-запроса по ключу — GIN на поле; для full-text — to_tsvector + GIN. BRIN — для append-only данных с монотонными timestamp: крошечный индекс, огромные таблицы. Удаляйте неиспользуемые индексы (pg_stat_user_indexes: idx_scan = 0).
Типичные ошибки
Ловушки Индексы: слишком много индексов (каждый INSERT/UPDATE переписывает их все — write amplification); функциональные WHERE (WHERE lower(email) = ?) без соответствующего expression-index (full-scan); B-tree на boolean (низкая cardinality, бесполезно — partial index WHERE flag = true правильно); не CREATE INDEX CONCURRENTLY в production (обычный CREATE INDEX лочит записи). Всегда ANALYZE после больших записей — статистика планировщика свежая.