Database Optimizer
When to Use / When Not to Use
Use when:
- EXPLAIN plan is in hand but the fix is server config, not query rewriting
- Investigating lock contention, VACUUM lag, or statistics staleness
- Tuning
shared_buffers, work_mem, or InnoDB buffer pool
- Designing partitioning strategy or index structure
Do not use when:
- The fix is rewriting a slow SQL query (use
sql-pro)
- The bottleneck is connection pool exhaustion (use
connection-pool-tuner)
Process
- Initial triage — Confirm: database engine + version, deployment type (self-managed vs. cloud-managed), and whether direct connection is available
- Capture baseline — Run
EXPLAIN (ANALYZE, BUFFERS) before any changes
- Identify bottlenecks — Find inefficient queries, missing indexes, config issues from the plan
- Design solutions — Index strategy, query rewrites, schema or config improvements
- Implement incrementally — One change at a time; validate each before proceeding
- Validate results — Re-run
EXPLAIN ANALYZE, compare costs, measure wall-clock improvement
On cloud-managed databases (RDS, Cloud SQL, Aurora): ALTER SYSTEM and my.cnf edits are unavailable. Use parameter groups or the console instead.
Use sequential-thinking if available — it enforces the baseline-capture step and prevents skipping directly to index creation.
Output Template
For each optimization task, provide:
- Performance analysis with baseline metrics (query time, cost, buffer hit ratio)
- Identified bottlenecks with EXPLAIN evidence
- Optimization strategy with specific changes
- Implementation SQL / config changes
- Validation queries to measure improvement
- Monitoring recommendations
What Claude Does / What You Do
| Claude |
You |
| Reads EXPLAIN output and identifies plan patterns |
Provide the actual EXPLAIN output |
| Recommends index type (B-tree, covering, partial, expression) |
Run CREATE INDEX CONCURRENTLY in your environment |
| Generates parameter tuning recommendations |
Apply via parameter group or ALTER SYSTEM |
| Writes validation queries to measure improvement |
Confirm improvement in production-scale data |
| Flags cloud-managed platform constraints |
Verify access level (console vs. direct connection) |
Reference Guide
| Topic |
Reference |
Load When |
| Query Optimization |
references/query-optimization.md |
Slow queries, execution plan analysis |
| Index Design |
references/index-design-patterns.md |
B-tree, covering, partial, expression indexes |
| PostgreSQL Memory & WAL |
references/postgresql-memory-wal.md |
shared_buffers, work_mem, WAL config |
| PostgreSQL VACUUM & Locking |
references/postgresql-vacuum-locking.md |
VACUUM, connection pooling, lock management |
| MySQL Memory & I/O |
references/mysql-memory-io.md |
InnoDB memory, I/O config |
| PostgreSQL Monitoring |
references/monitoring-postgresql.md |
pg_stat_statements, connections, locks |
| MySQL Monitoring |
references/monitoring-mysql.md |
Performance schema, InnoDB status |
EXPLAIN Output — Key Patterns
| Pattern |
Symptom |
Typical Remedy |
Seq Scan on large table |
No filter selectivity |
Add B-tree index on filter column |
Nested Loop with large outer set |
Exponential row growth |
Consider Hash Join; index inner join key |
cost=... rows=1 but actual rows=50000 |
Stale statistics |
Run ANALYZE <table> |
Buffers: hit=10 read=90000 |
Low cache hit rate |
Increase shared_buffers; add covering index |
Sort Method: external merge |
Sort spilling to disk |
Increase work_mem for the session |
-- Always use BUFFERS to see cache hit vs. disk read ratio
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT o.id, c.name
FROM orders o
JOIN customers c ON c.id = o.customer_id
WHERE o.status = 'pending'
AND o.created_at > now() - interval '7 days';
Constraints
MUST DO:
- Capture
EXPLAIN (ANALYZE, BUFFERS) before any changes — this is the baseline
- Create PostgreSQL indexes with
CONCURRENTLY to avoid table locks
- Test in non-production; roll back if write performance or replication lag worsens
- Make one change at a time — measure before making the next change
MUST NOT DO:
- Apply optimizations without a measured baseline
- Create redundant or unused indexes
- Make multiple changes simultaneously
- Use
ALTER SYSTEM on Amazon RDS or other cloud-managed databases
Related Skills
sql-pro — rewriting slow queries when the server is correctly configured
connection-pool-tuner — pool sizing after server config is validated
sre-engineer — monitoring and alerting on database golden signals
1---2name: database-optimizer3description: Use when database slowness stems from infrastructure concerns rather than query authoring: server memory and I/O configuration, connection pooling, lock contention, VACUUM and statistics maintenance, partitioning design, or cloud-managed database...4license: MIT5---67# Database Optimizer89## When to Use / When Not to Use1011**Use when:**12- EXPLAIN plan is in hand but the fix is server config, not query rewriting13- Investigating lock contention, VACUUM lag, or statistics staleness14- Tuning `shared_buffers`, `work_mem`, or InnoDB buffer pool15- Designing partitioning strategy or index structure1617**Do not use when:**18- The fix is rewriting a slow SQL query (use `sql-pro`)19- The bottleneck is connection pool exhaustion (use `connection-pool-tuner`)2021## Process22231. **Initial triage** — Confirm: database engine + version, deployment type (self-managed vs. cloud-managed), and whether direct connection is available242. **Capture baseline** — Run `EXPLAIN (ANALYZE, BUFFERS)` before any changes253. **Identify bottlenecks** — Find inefficient queries, missing indexes, config issues from the plan264. **Design solutions** — Index strategy, query rewrites, schema or config improvements275. **Implement incrementally** — One change at a time; validate each before proceeding286. **Validate results** — Re-run `EXPLAIN ANALYZE`, compare costs, measure wall-clock improvement2930> On cloud-managed databases (RDS, Cloud SQL, Aurora): `ALTER SYSTEM` and `my.cnf` edits are unavailable. Use parameter groups or the console instead.3132Use `sequential-thinking` if available — it enforces the baseline-capture step and prevents skipping directly to index creation.3334## Output Template3536For each optimization task, provide:371. Performance analysis with baseline metrics (query time, cost, buffer hit ratio)382. Identified bottlenecks with EXPLAIN evidence393. Optimization strategy with specific changes404. Implementation SQL / config changes415. Validation queries to measure improvement426. Monitoring recommendations4344## What Claude Does / What You Do4546| Claude | You |47|--------|-----|48| Reads EXPLAIN output and identifies plan patterns | Provide the actual EXPLAIN output |49| Recommends index type (B-tree, covering, partial, expression) | Run `CREATE INDEX CONCURRENTLY` in your environment |50| Generates parameter tuning recommendations | Apply via parameter group or `ALTER SYSTEM` |51| Writes validation queries to measure improvement | Confirm improvement in production-scale data |52| Flags cloud-managed platform constraints | Verify access level (console vs. direct connection) |5354## Reference Guide5556| Topic | Reference | Load When |57|-------|-----------|-----------|58| Query Optimization | `references/query-optimization.md` | Slow queries, execution plan analysis |59| Index Design | `references/index-design-patterns.md` | B-tree, covering, partial, expression indexes |60| PostgreSQL Memory & WAL | `references/postgresql-memory-wal.md` | shared_buffers, work_mem, WAL config |61| PostgreSQL VACUUM & Locking | `references/postgresql-vacuum-locking.md` | VACUUM, connection pooling, lock management |62| MySQL Memory & I/O | `references/mysql-memory-io.md` | InnoDB memory, I/O config |63| PostgreSQL Monitoring | `references/monitoring-postgresql.md` | pg_stat_statements, connections, locks |64| MySQL Monitoring | `references/monitoring-mysql.md` | Performance schema, InnoDB status |6566## EXPLAIN Output — Key Patterns6768| Pattern | Symptom | Typical Remedy |69|---------|---------|----------------|70| `Seq Scan` on large table | No filter selectivity | Add B-tree index on filter column |71| `Nested Loop` with large outer set | Exponential row growth | Consider Hash Join; index inner join key |72| `cost=... rows=1` but actual rows=50000 | Stale statistics | Run `ANALYZE <table>` |73| `Buffers: hit=10 read=90000` | Low cache hit rate | Increase `shared_buffers`; add covering index |74| `Sort Method: external merge` | Sort spilling to disk | Increase `work_mem` for the session |7576```sql77-- Always use BUFFERS to see cache hit vs. disk read ratio78EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)79SELECT o.id, c.name80FROM orders o81JOIN customers c ON c.id = o.customer_id82WHERE o.status = 'pending'83 AND o.created_at > now() - interval '7 days';84```8586## Constraints8788**MUST DO:**89- Capture `EXPLAIN (ANALYZE, BUFFERS)` before any changes — this is the baseline90- Create PostgreSQL indexes with `CONCURRENTLY` to avoid table locks91- Test in non-production; roll back if write performance or replication lag worsens92- Make one change at a time — measure before making the next change9394**MUST NOT DO:**95- Apply optimizations without a measured baseline96- Create redundant or unused indexes97- Make multiple changes simultaneously98- Use `ALTER SYSTEM` on Amazon RDS or other cloud-managed databases99100## Related Skills101102- `sql-pro` — rewriting slow queries when the server is correctly configured103- `connection-pool-tuner` — pool sizing after server config is validated104- `sre-engineer` — monitoring and alerting on database golden signals