Мини-гайд: Индексы в PostgreSQL — быстро и по делу

GuDron

dumpz.ws
Admin
Регистрация
28 Янв 2020
Сообщения
10,705
Реакции
1,629
Credits
40,248
Индексы — главный инструмент для ускорения запросов. Но неправильное использование может только навредить.

Основные типы индексов в PostgreSQL:
- B-tree — по умолчанию. Идеален для поиска по равенству и диапазону (=, <, >, BETWEEN).
- Hash — только для поиска по точному равенству (=). Становится актуальным реже.
- GIN — для массивов, JSONB, полнотекстового поиска.
- GiST — геоданные, поиск по диапазонам, сложные типы.
- BRIN — для очень больших таблиц с упорядоченными данными (например, логи).

Практические советы:
- Не злоупотребляй индексами: каждый индекс замедляет INSERT/UPDATE/DELETE.
- Следи за актуальностью: периодически проверяй и удаляй неиспользуемые (pg_stat_user_indexes поможет).
- Составные индексы ((col1, col2)) эффективны, только если условия WHERE учитывают порядок колонок.
- Используй EXPLAIN ANALYZE, чтобы понять, работает ли индекс в реальности.

Типичная ошибка:
Создать индекс на всё подряд без анализа запросов. Итог — тормоза на записи и огромный размер базы.

Индексы — это как специи: мало — пресно, много — несъедобно.

Вывод:
Хотите быструю базу — планируйте индексацию так же внимательно, как сами запросы.
 

GuDron

dumpz.ws
Admin
Регистрация
28 Янв 2020
Сообщения
10,705
Реакции
1,629
Credits
40,248
Мини-гайд: Индексы в PostgreSQL

1. Зачем нужны индексы?

▪️ Ускоряют SELECT, JOIN, ORDER BY, GROUP BY.
▪️Снижают нагрузку при выборках без полного сканирования таблицы.

2. Типы индексов
▪️B-tree (по умолчанию): точный поиск (=), диапазоны (<, >), сортировки.
SQL:
CREATE INDEX idx_users_email ON users(email);
▪️Hash: для точного сравнения, но используется редко.
▪️GIN: массивы и полнотекстовый поиск.
SQL:
CREATE INDEX idx_docs_content
 ON documents USING GIN(to_tsvector('russian', content));
▪️GiST: геоданные (PostGIS), диапазоны (int4range, tsrange).
▪️BRIN: очень большие таблицы, где данные «почти упорядочены» (по дате).
SQL:
CREATE INDEX idx_logs_created_at
 ON logs USING BRIN(created_at);

3. Практические советы
▪️Оценивайте запросы через EXPLAIN ANALYZE или pg_stat_statements.
▪️Не создавайте индекс «про запас»: каждый замедляет INSERT/UPDATE/DELETE.
▪️Составные индексы: порядок колонок критичен.
SQL:
CREATE INDEX idx_users_city_age
 ON users(city, age);
▪️Избегайте низкокардинальных колонок (boolean, ENUM) — индекс неэффективен, если фильтр возвращает большинство строк.
▪️Актуализируйте статистику: запускайте ANALYZE после больших загрузок/удалений.
▪️Удаляйте устаревшие индексы:
SQL:
DROP INDEX IF EXISTS idx_old_column;
▪️Используйте REINDEX для устранения фрагментации:
SQL:
REINDEX INDEX idx_users_email;

4. Подводные камни
▪️Бесполезный индекс: если WHERE возвращает ≥90% строк (например, is_active = true при 99% активных).
▪️Функциональные индексы: CREATE INDEX ON table ((LOWER(name))) сработает только при точном вызове WHERE LOWER(name) = 'ivan'.
▪️Блокировки: для создания без блокировки пишите:
SQL:
CREATE INDEX CONCURRENTLY idx_orders_status ON orders(status);
Но этот процесс дольше и требует больше места.
▪️Индексы на внешних ключах: без них при удалении/обновлении родительской записи будут долгие сканы.

Итог:
Индексы — мощный инструмент, если их грамотно использовать. Анализируйте планы запросов, не создавайте лишних, следите за статистикой и удаляйте устаревшие.