Operational guidance for running query optimization in production environments. Complements the tuning workflow in Lesson 07.
Before deploying any query optimization change:
-- Prefer CONCURRENTLY on production tables to avoid a blocking ACCESS EXCLUSIVE lock.
-- Tradeoffs: cannot run inside a transaction block, takes longer, and can leave an
-- INVALID index behind on failure (drop and retry in that case).
CREATE INDEX CONCURRENTLY idx_name ON table_name (column);
-- Monitor progress
SELECT * FROM pg_stat_progress_create_index;
-- Drop unused index safely
DROP INDEX CONCURRENTLY idx_name;
-- Online DDL (InnoDB)
ALTER TABLE table_name ADD INDEX idx_name (column), ALGORITHM=INPLACE, LOCK=NONE;
CREATE INDEX idx_name ON table_name (column) WITH (ONLINE = ON);
| Event | Action | Priority |
|---|---|---|
| After bulk load (> 10% table growth) | ANALYZE immediately |
Critical |
| After major DELETE | ANALYZE within 1 hour |
High |
| After schema change (new column/index) | ANALYZE before traffic |
High |
| Weekly (high-churn tables) | Scheduled ANALYZE |
Medium |
| Monthly (stable tables) | Review auto-analyze settings | Low |
-- Enable pg_stat_statements
CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
-- Log queries > 1 second
ALTER SYSTEM SET log_min_duration_statement = 1000;
SELECT pg_reload_conf();
-- Top 10 by total time
SELECT query, calls, mean_exec_time, total_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC LIMIT 10;
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;
SET GLOBAL log_queries_not_using_indexes = ON;
| Severity | Response Time | Actions |
|---|---|---|
| SEV-1 (outage) | Immediate | Kill long-running queries, check locks, failover to replica |
| SEV-2 (degraded) | 15 minutes | EXPLAIN ANALYZE, identify bottleneck, apply targeted fix |
| SEV-3 (slow trend) | Next business day | Review pg_stat_statements, plan regression check |
Query optimization reduces per-query time, but connection pool exhaustion looks identical to slow queries:
statement_timeout to prevent runaway queries from holding connections