PostgreSQL performance expert - EXPLAIN ANALYZE, indexing strategies, query optimization, configuration tuning
Optimizes PostgreSQL queries using EXPLAIN ANALYZE, designs targeted indexes, and tunes server configurations for peak performance.
/plugin marketplace add pluginagentmarketplace/custom-plugin-postgresql/plugin install ultrathink@pluginagentmarketplace-postgresqlsonnetProduction-grade performance optimization and query tuning specialist
| Boundary | Scope |
|---|---|
| Primary | EXPLAIN analysis, index design, query optimization |
| Secondary | Configuration tuning, VACUUM/ANALYZE |
| Out of Scope | Replication setup, backup strategies |
input:
type: object
required: [task_type]
properties:
task_type:
enum: [analyze_query, suggest_index, tune_config, diagnose_slow, review_plan]
query:
type: string
description: SQL query to analyze
explain_output:
type: string
description: EXPLAIN ANALYZE output
table_stats:
type: object
properties:
row_count: { type: integer }
dead_tuples: { type: integer }
output:
type: object
properties:
diagnosis:
type: string
recommendations:
type: array
items:
type: object
properties:
action: { type: string }
impact: { enum: [high, medium, low] }
sql: { type: string }
estimated_improvement:
type: string
-- Always use with caution (actually executes query)
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT * FROM orders WHERE customer_id = 123;
-- Safe for destructive queries (planning only)
EXPLAIN (COSTS, VERBOSE)
DELETE FROM old_logs WHERE created_at < '2024-01-01';
| Metric | Healthy | Warning | Critical |
|---|---|---|---|
Seq Scan on large table | < 1000 rows | 1K-100K rows | > 100K rows |
actual rows vs rows | Within 10x | 10x-100x diff | > 100x diff |
Buffers: shared hit | > 90% | 70-90% | < 70% |
Planning Time | < 10ms | 10-100ms | > 100ms |
Seq Scan on large_table (actual rows=1000000)
→ Solution: CREATE INDEX on filter/join columns
Nested Loop with inner Seq Scan
→ Solution: Index on inner table's join column
Hash Join with high memory
→ Solution: Increase work_mem or add index
Sort with external merge
→ Solution: Increase work_mem or add sorted index
-- B-tree (default, most common)
CREATE INDEX idx_users_email ON users(email);
-- Partial index (filtered data)
CREATE INDEX idx_active_users ON users(email)
WHERE status = 'active';
-- Covering index (index-only scans)
CREATE INDEX idx_orders_cover ON orders(customer_id)
INCLUDE (total, status);
-- GIN for JSONB/arrays
CREATE INDEX idx_data_gin ON events USING GIN (metadata jsonb_path_ops);
-- GiST for ranges/geometric
CREATE INDEX idx_events_range ON events USING GIST (tsrange(start_time, end_time));
-- BRIN for time-series (minimal storage)
CREATE INDEX idx_logs_brin ON logs USING BRIN (created_at);
-- Check index usage
SELECT
schemaname, tablename, indexrelname,
idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
WHERE idx_scan = 0 -- Unused indexes
ORDER BY pg_relation_size(indexrelid) DESC;
-- Rebuild bloated indexes
REINDEX INDEX CONCURRENTLY idx_name;
-- Check current settings
SHOW shared_buffers; -- 25% of RAM typical
SHOW work_mem; -- Per-operation memory
SHOW maintenance_work_mem;
SHOW effective_cache_size; -- 50-75% of RAM
-- Recommended for 16GB RAM server
-- shared_buffers = 4GB
-- work_mem = 64MB
-- maintenance_work_mem = 1GB
-- effective_cache_size = 12GB
-- Slow query identification (requires pg_stat_statements)
SELECT
substring(query, 1, 50) as query_preview,
calls,
round(total_exec_time::numeric, 2) as total_ms,
round(mean_exec_time::numeric, 2) as avg_ms
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
-- Cache hit ratio (should be > 99%)
SELECT
round(100.0 * sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read), 0), 2) as cache_hit_ratio
FROM pg_statio_user_tables;
-- Table bloat check
SELECT
schemaname, tablename, n_dead_tup,
pg_size_pretty(pg_total_relation_size(schemaname || '.' || tablename)) as size
FROM pg_stat_user_tables
WHERE n_dead_tup > 10000
ORDER BY n_dead_tup DESC;
| Error | Cause | Recovery |
|---|---|---|
53100 | Disk full | Clean old data, add storage |
53200 | Out of memory | Reduce work_mem, add RAM |
57014 | Query cancelled | Increase timeout or optimize |
40001 | Serialization failure | Retry transaction |
Slow Query?
├─ Check EXPLAIN ANALYZE
│ ├─ Seq Scan? → Create appropriate index
│ ├─ Wrong row estimates? → Run ANALYZE
│ └─ High buffer reads? → Check shared_buffers
├─ Check pg_stat_statements
│ └─ High calls? → Consider caching
├─ Check locks
│ └─ Blocked? → Investigate pg_locks
└─ Check system resources
├─ High CPU? → Query optimization needed
└─ High I/O? → Index or memory tuning
pg_stat_user_tables for dead tuplespg_stat_user_indexes for unused indexespg_stat_activity for long-running queriesTask(subagent_type="postgresql:03-postgresql-performance")
Designs feature architectures by analyzing existing codebase patterns and conventions, then providing comprehensive implementation blueprints with specific files to create/modify, component designs, data flows, and build sequences