Hash Indexes
standardintermediateA Hash index stores a hash code of the indexed value and supports ONLY equality (=) comparisons — no ranges, no ORDER BY, no BETWEEN. Because a B-tree already handles equality just as well while also supporting range queries and sorting, Hash indexes are rarely the right choice in practice; B-tree is preferred even for pure-equality workloads unless a specific, measured reason says otherwise.
Think of it as
A Hash index is a narrower tool than a B-tree in every dimension except one: for pure equality lookups on very simple types, its lookup can theoretically be marginally cheaper since a hash comparison is simpler than a tree traversal. In practice, this theoretical edge rarely translates into a compelling reason to give up everything a B-tree offers (range queries, sorting, uniqueness) for a type of comparison a B-tree already handles well — which is exactly why Hash indexes are the least commonly reached-for index type in ordinary schema design.
What we're doing: Confirm a Hash index is rejected for a range query that a B-tree on the same column would happily serve.
- 3–4
- Exactly the one thing a Hash index supports — equality — works as expected.
- 6–8
- A range comparison, something B-tree handles trivially, has no possible plan using this Hash index at all.
-- equality: Index Scan using the hash index
-- range: Seq Scan -- no hash-index plan exists for this query shapeWhy this works: This demonstrates the Hash index's real limitation directly: it is not merely less efficient for a range query, it is structurally incapable of answering one at all — there is no plan node that could use a Hash index for anything other than an equality comparison, which is exactly the trade-off that makes B-tree the safer default even for equality-heavy workloads.
Choosing a Hash index for a column expecting to need range queries later
Wrong
Better
What you see: A new query pattern (a range filter, or an ORDER BY) that a B-tree would have served automatically instead requires an entirely new index to be created on the same column, because the existing Hash index cannot be adapted or reused for it.
Why: Choosing Hash instead of B-tree gives up range and sort support with no offsetting benefit for most real workloads, which is exactly why B-tree is the recommended default even when the CURRENT query pattern is equality-only — a B-tree costs nothing extra for that case while staying flexible for query patterns that may emerge later.
Hash vs B-tree, for an equality-only workload
Remember: A Hash index supports only equality (=) — no ranges, no ORDER BY, and it cannot be UNIQUE. B-tree already handles equality just as well while also supporting everything Hash cannot, which is why B-tree remains the default even for equality-only workloads — reach for Hash only with a specific, measured reason.
See also: the default b tree index · gist and sp gist use cases

