lesson ── postgres-labs ── ~20 мин ── 4 шагов
Hash-индекс умеет ровно одно - равенство. Построим его, проверим, что он
ускоряет =, но бессилен против диапазона, и сравним с B-tree. Запусти
psql во вкладке client.
интерактивный sandbox
Поднимется контейнер postgreslab/postgres-base с PostgreSQL 17 и psql. В браузере откроется терминал, база lab уже настроена. Каждый шаг проверяется автоматически. Сеть air-gapped, наружу контейнер не ходит.
stack ── PostgreSQL 17 · psql · 1 GB RAM · air-gapped · самоуничтожается через 45 мин простоя
CREATE TABLE big AS SELECT g AS id, md5(g::text) AS h FROM generate_series(1, 500000) g;
ANALYZE big;
md5 даёт длинный текстовый ключ - на нём интересно сравнивать размеры.
✓ Таблица готова.
CREATE INDEX h_h ON big USING hash (h);
ANALYZE big;
EXPLAIN SELECT * FROM big WHERE h = md5('42');По равенству hash находит строку за одно-два обращения.
Hash ищет по 4-байтному хешу ключа, без спуска по дереву.
✓ Равенство ушло в hash-индекс.
EXPLAIN SELECT * FROM big WHERE h > md5('1');У нас только hash-индекс, а он не умеет порядок - план Seq Scan. Предскажи это до запуска.
Порядок хеша не связан с порядком значений - диапазон невозможен.
✓ Seq Scan - hash не делает диапазоны.
CREATE INDEX b_h ON big USING btree (h);
ANALYZE big;
EXPLAIN SELECT * FROM big WHERE h > md5('999999');Теперь диапазон обслуживает B-tree. Сравни размеры обоих индексов
через \di+ h_h и \di+ b_h.
B-tree покрывает и равенство, и диапазон - поэтому он по умолчанию.
✓ Диапазон обслуживает B-tree - он универсальнее hash.
Hash-индекс поддерживает только равенство и ищет по хешу за одно-два обращения; диапазоны, сортировку и многоколоночность он не умеет. B-tree покрывает и равенство, и диапазон, поэтому остаётся выбором по умолчанию. Hash - осознанный выбор под строгое равенство по длинному ключу.
команды
CREATE INDEX ON t USING hash (col);hash-индекс под равенство\di+ idxсравнить размер индексовконцепции