PostgreSQL Index Types and Strategies

Use PostgreSQL B-tree, GIN, GiST, BRIN, partial indexes, expression indexes, and concurrent builds effectively.

View
StandardDetailedCompact
Export
Copy the compact sheet, download it, or print it.
Download
`D` dense toggle · `C` copy all

PostgreSQL index types

Choose the right index method for the workload.

B-tree index

Default choice for equality, ranges, and ordering.

sqlANYpostgresqlbtree
sql
CREATE INDEX idx_products_sku ON products (sku);

B-tree is the default and best starting point for many OLTP queries.

GIN index on JSONB

Speed containment queries on JSONB data.

sqlANYpostgresqlginjsonb
sql
CREATE INDEX idx_events_payload_gin ON events USING GIN (payload jsonb_path_ops);

GIN is often used for composite or document-like structures such as JSONB and arrays.

BRIN index for large append-heavy tables

Use BRIN when physical order correlates with query ranges.

sqlANYpostgresqlbrintime-series
sql
CREATE INDEX idx_logs_created_at_brin ON logs USING BRIN (created_at);

BRIN can be compact and effective for very large time-series or append-only tables.

Expression index

Index the result of an expression used in predicates.

sqlANYpostgresqlexpression-index
sql
CREATE INDEX idx_users_lower_email ON users ((lower(email)));

Expression indexes help when the query applies a function such as `lower(email)`.

Partial index

Index only the rows a hot query actually needs.

sqlANYpostgresqlpartial-index
sql
CREATE INDEX idx_orders_unshipped ON orders (created_at) WHERE shipped_at IS NULL;

Partial indexes reduce size and write cost when the workload focuses on a subset of rows.

Create index concurrently

Reduce blocking on busy tables.

sqlANYpostgresqlconcurrentlymigrations
sql
CREATE INDEX CONCURRENTLY idx_orders_user_id ON orders (user_id);

Concurrent index builds are useful in production migrations when minimizing write blocking matters.

Plan inspection

Verify that the planner uses the index the way you expect.

Explain with runtime stats

Inspect actual execution behavior.

sqlANYpostgresqlexplainanalyze
sql
EXPLAIN (ANALYZE, BUFFERS)
SELECT *
FROM orders
WHERE shipped_at IS NULL
ORDER BY created_at DESC
LIMIT 100;

This is one of the most useful PostgreSQL performance tools for validating index choices.

Recommended next

No recommendations yet.