Database indexing strategies for performance

Maria Garcia Feb 2026
2 tabs
-- Create basic index
CREATE INDEX idx_users_email ON users(email);

-- Unique index (enforces uniqueness)
CREATE UNIQUE INDEX idx_users_username ON users(username);

-- Composite index (column order matters!)
CREATE INDEX idx_orders_user_status_date
  ON orders(user_id, status, created_at);

-- This index helps queries like:
-- WHERE user_id = ? AND status = ? AND created_at > ?
-- WHERE user_id = ? AND status = ?
-- WHERE user_id = ?
-- But NOT: WHERE status = ? (doesn't use index efficiently)

-- Partial index (PostgreSQL): Index subset of rows
CREATE INDEX idx_orders_pending
  ON orders(created_at)
  WHERE status = 'pending';

-- Covering index: Include extra columns
CREATE INDEX idx_users_email_covering
  ON users(email)
  INCLUDE (name, created_at);  -- PostgreSQL 11+

-- Or in MySQL:
CREATE INDEX idx_users_email_name
  ON users(email, name, created_at);

-- Expression index
CREATE INDEX idx_users_lower_email
  ON users(LOWER(email));

-- Helps with case-insensitive searches:
-- WHERE LOWER(email) = 'user@example.com'

-- Descending index for ORDER BY DESC
CREATE INDEX idx_posts_created_desc
  ON posts(created_at DESC);

-- Check index usage
SELECT
  schemaname,
  tablename,
  indexname,
  idx_scan as index_scans,
  idx_tup_read as tuples_read,
  idx_tup_fetch as tuples_fetched
FROM pg_stat_user_indexes
ORDER BY idx_scan ASC;
2 files · sql Explain with highlit

Indexes dramatically speed up queries but slow down writes. B-tree indexes handle equality and range queries—default for most databases. I create indexes on foreign keys, frequently queried columns, and WHERE/ORDER BY clauses. Composite indexes order matters—most selective column first. Partial indexes filter rows, reducing index size. Covering indexes include all query columns, avoiding table lookups. UNIQUE indexes enforce constraints while providing lookup speed. Full-text indexes enable text search. Analyze query plans with EXPLAIN to identify missing indexes. Over-indexing wastes space and slows writes. Regular REINDEX maintains performance. Understanding index types—B-tree, Hash, GiST, GIN—optimizes different workloads.