Indexing in PostgreSQL
Definition
PostgreSQL supports multiple index types including B-tree, Hash, GiST, GIN, BRIN, and SP-GiST, each optimized for different data types and query patterns.
Introduction to Indexing in PostgreSQL
PostgreSQL offers the most diverse index type selection of any open-source database. Beyond the standard B-tree index, PostgreSQL's GIN indexes power full-text search and JSONB queries, GiST handles geometric and range data, and BRIN provides efficient coverage for naturally ordered large tables.
Syntax
-- Standard B-tree
CREATE INDEX idx_col ON table(col);
-- GIN for full-text / JSONB
CREATE INDEX idx_fts ON articles USING GIN(to_tsvector('english', body));
-- Partial index (only indexes rows matching condition)
CREATE INDEX idx_active ON orders(customer_id) WHERE status = 'active';
-- Expression index
CREATE INDEX idx_lower_email ON users(LOWER(email));Examples
Partial Index for Active Records
-- Only index active orders (not archived) CREATE INDEX idx_active_orders_customer ON orders(customer_id, created_at) WHERE status = 'active'; -- This query uses the partial index (much smaller than full index) SELECT * FROM orders WHERE customer_id = 42 AND status = 'active' ORDER BY created_at DESC;
Partial indexes are smaller, faster, and cheaper to maintain than full indexes. If 90% of orders are archived, the partial index covers only 10% of rows.
Try in PlaygroundGIN Index for JSONB
CREATE INDEX idx_user_prefs ON users USING GIN(preferences);
-- Now these JSONB queries use the index:
SELECT * FROM users WHERE preferences @> '{"theme": "dark"}';
SELECT * FROM users WHERE preferences ? 'newsletter';GIN (Generalized Inverted Index) indexes all keys and values in a JSONB column, enabling fast @> (contains) and ? (key exists) operators.
Try in PlaygroundCommon Mistakes
Using a regular B-tree index on a JSONB column — use GIN instead
Creating indexes without CONCURRENTLY on production tables — locks the table during build
Forgetting to run VACUUM ANALYZE after bulk data changes
Not using expression indexes for case-insensitive lookups (use LOWER(email))
Frequently Asked Questions
What index types does PostgreSQL support?
What is a partial index in PostgreSQL?
How do you create indexes without locking the table in PostgreSQL?
Related SQL Topics
Practice This in the SQL Playground
Write real queries, see live results, and master Indexing in PostgreSQL hands-on. 100% free.