PostgreSQL gives us more than just B-tree indexes. If you’re working with read-heavy applications or complex data, understanding the right type of index can make or break your performance.
Let’s explore the main index types in PostgreSQL with examples to help you choose wisely.
🔸 B-tree Index (Default)
B-tree is PostgreSQL’s default and most common index type. It works great for:
- Equality comparisons:
=
- Range queries:
<
,>
,BETWEEN
- Sorting operations
âś… Example:
CREATE INDEX idx_users_email ON users(email);
-- Supports: WHERE email = '[email protected]'
🔸 Hash Index
Hash indexes are optimized for equality-only lookups. They’re slightly faster than B-tree for = queries, but they don’t support sorting or range queries.
âś… Example:
CREATE INDEX idx_users_api_key_hash ON users USING hash(api_key);
-- Supports: WHERE api_key = 'xyz123'
🔸 GIN (Generalized Inverted Index)
GIN is ideal for indexing data types that contain multiple values, such as:
Arrays
JSONB
Full-text search
âś… Example:
CREATE INDEX idx_users_api_key_hash ON users USING hash(api_key);
-- Supports: WHERE api_key = 'xyz123'
đź’ˇ Perfect for filtering inside JSON or searching across multiple tags/keywords.
🔸 BRIN (Block Range Index)
BRIN indexes store summaries of value ranges for blocks of data—not individual rows. They’re very small and fast to create.
âś… Example:
CREATE INDEX idx_logs_created_at ON logs USING brin(created_at);
-- Supports: WHERE created_at > now() - interval '1 day'
đź’ˇ Use for large, append-only tables (logs, metrics, time-series).
🔸 GiST (Generalized Search Tree)
GiST is a flexible indexing framework that supports complex data like:
Geometric types (points, polygons)
Ranges (e.g., int4range, tsrange)
Custom types
âś… Example:
CREATE INDEX idx_locations_geom ON locations USING gist(geom);
-- Supports: WHERE ST_DWithin(geom, ST_MakePoint(...), 500)
đź’ˇ Best for apps dealing with maps, coordinates, or advanced data types.
Final Thoughts
Choosing the right index type helps balance read speed, storage, and write performance. Always consider:
Query pattern (equality vs range vs search)
Data structure (flat vs nested)
Table size and growth behavior
Use EXPLAIN ANALYZE to validate your decisions, and don’t be afraid to combine index types across columns.
Let PostgreSQL work with you—not against you 🚀
Have a favorite index or optimization trick? Share it below 👇
Top comments (0)