SQL Optimization Techniques Every Developer Should Know
Query performance can make or break an application. A single poorly optimized query can bring a database to its knees during peak load. Here are the techniques that consistently deliver results.
1. Understand EXPLAIN Plans
Before optimizing, you need to understand what's happening. Learn to read execution plans:
EXPLAIN ANALYZE
SELECT o.order_id, c.customer_name
FROM orders o
JOIN customers c ON o.customer_id = c.id
WHERE o.created_at > '2024-01-01';
Key things to look for:
- Sequential scans on large tables (usually bad)
- Index scans (usually good)
- Nested loops vs. hash joins
- Estimated vs. actual row counts
2. Index Strategy
Indexes are powerful but not free. Consider these patterns:
-- Composite index for common query pattern
CREATE INDEX idx_orders_customer_date
ON orders (customer_id, created_at DESC);
-- Partial index for specific use case
CREATE INDEX idx_orders_pending
ON orders (created_at)
WHERE status = 'pending';
-- Covering index to avoid table lookup
CREATE INDEX idx_orders_summary
ON orders (customer_id)
INCLUDE (total_amount, status);
3. Avoid N+1 Queries
This common anti-pattern kills performance. Instead of:
-- BAD: N+1 pattern
for customer_id in customer_ids:
query = f"SELECT * FROM orders WHERE customer_id = {customer_id}"
Use a single query with IN clause or JOIN:
-- GOOD: Single query
SELECT * FROM orders
WHERE customer_id = ANY(%(customer_ids)s);
4. Pagination Done Right
OFFSET-based pagination gets slower as you go deeper. Use keyset pagination instead:
-- Instead of OFFSET (slow for deep pages)
SELECT * FROM orders
ORDER BY created_at DESC
LIMIT 20 OFFSET 10000;
-- Use keyset pagination (consistent performance)
SELECT * FROM orders
WHERE created_at < '2024-02-15 10:30:00'
ORDER BY created_at DESC
LIMIT 20;
5. Batch Operations
For bulk inserts and updates, batch your operations:
-- Batch insert
INSERT INTO orders (customer_id, amount)
VALUES
(1, 100.00),
(2, 150.00),
(3, 200.00)
ON CONFLICT (order_id) DO UPDATE
SET amount = EXCLUDED.amount;
These techniques have solved 90% of the performance issues I've encountered. Master them before reaching for more complex solutions.