Hash индекс

Тема дорожной карты · PostgreSQL

Хэш-индекс в PostgreSQL — это тип индекса, оптимизированный исключительно для проверки равенства (=): он хранит хэш каждого индексируемого значения вместе с указателем на кортеж в основной таблице, обеспечивая быстрый поиск со средней сложностью O(1). Созданный командой CREATE INDEX ON users USING HASH (email), хэш-индекс может превосходить по скорости индекс B-tree в рабочих нагрузках с исключительно точечными запросами на равенство, поскольку формирует более компактные записи индекса и не требует обхода дерева, присущего B-tree. До PostgreSQL 10 хэш-индексы не записывались в WAL и считались небезопасными для использования в продуктивных реляционных базах данных; начиная с PostgreSQL 10 они полностью безопасны при сбоях и реплицируются, что делает их жизнеспособным выбором для сценариев с большими объёмами точечных запросов. Хэш-индексы не поддерживают диапазонные запросы, ORDER BY и составные индексы, поэтому стандартная рекомендация по оптимизации запросов PostgreSQL — использовать хэш-индексы только при доказуемо исключительно точечных шаблонах доступа и высокой мощности индексируемого столбца.

Как это работает

Hash индекс ускоряют чтение ценой записи + 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).

Типичные ошибки

Ловушки Hash индекс: слишком много индексов (каждый 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 после больших записей — статистика планировщика свежая.

Связанные понятия

Полезные ресурсы