Skip to content

Instantly share code, notes, and snippets.

@mohashari
Created March 14, 2026 15:12
Show Gist options
  • Select an option

  • Save mohashari/42ed858dddc9f02021880443120f21c4 to your computer and use it in GitHub Desktop.

Select an option

Save mohashari/42ed858dddc9f02021880443120f21c4 to your computer and use it in GitHub Desktop.
Code snippets — Database Indexing Strategies
-- After creating the foreign key
ALTER TABLE orders ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id);
-- Always add this index
CREATE INDEX idx_orders_user_id ON orders(user_id);
REINDEX INDEX CONCURRENTLY idx_orders_user_id;
-- This CANNOT use an index on created_at
WHERE DATE(created_at) = '2026-01-01'
-- This CAN
WHERE created_at >= '2026-01-01' AND created_at < '2026-01-02'
CREATE INDEX idx_sessions_token ON sessions USING HASH (token);
-- Full text search
CREATE INDEX idx_articles_search ON articles USING GIN (to_tsvector('english', content));
-- JSONB
CREATE INDEX idx_users_metadata ON users USING GIN (metadata);
-- This index serves both queries below efficiently
CREATE INDEX idx_orders_user_status ON orders(user_id, status, created_at);
-- Uses the index
SELECT * FROM orders WHERE user_id = 42 AND status = 'pending';
-- Also uses the index (partial)
SELECT * FROM orders WHERE user_id = 42;
-- Does NOT use the index efficiently
SELECT * FROM orders WHERE status = 'pending';
-- Query needs user_id, status, and total
SELECT user_id, status, total FROM orders WHERE user_id = 42;
-- Covering index includes all needed columns
CREATE INDEX idx_orders_covering ON orders(user_id) INCLUDE (status, total);
-- Only index unprocessed jobs (90% are already processed)
CREATE INDEX idx_jobs_pending ON jobs(created_at)
WHERE status = 'pending';
-- Only index active users
CREATE INDEX idx_users_active_email ON users(email)
WHERE deleted_at IS NULL;
-- Case-insensitive email lookup
CREATE INDEX idx_users_lower_email ON users(LOWER(email));
-- Now this query is fast
SELECT * FROM users WHERE LOWER(email) = LOWER('User@Example.com');
-- Enable timing
\timing
-- See the query plan
EXPLAIN ANALYZE
SELECT * FROM orders WHERE user_id = 42 AND status = 'pending';
-- Look for:
-- "Seq Scan" — full table scan (bad for large tables)
-- "Index Scan" — good
-- "Index Only Scan" — best
-- actual time vs estimated time
-- Find the most time-consuming queries
SELECT query, mean_exec_time, calls, total_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_orders_created ON orders(created_at);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment