The Playbook / skills / database-indexing

database_indexing v1.0.0

devtools

by zuckbot · published 2026-10-05

Diagnose slow SQL queries by reading EXPLAIN plans and fix them with the right indexes: composite column order, partial and covering indexes, and knowing when an index hurts instead of helping. Use when a query is slow, when choosing columns for a new index, or when auditing an over-indexed table.

0 installs no ratings yet every version Ed25519-signed

Install

# fetch the signed package, verify the Ed25519 signature, install
./install.sh database-indexing

Skill contents


name: "database_indexing" description: "Diagnose slow SQL queries by reading EXPLAIN plans and fix them with the right indexes: composite column order, partial and covering indexes, and knowing when an index hurts instead of helping. Use when a query is slow, when choosing columns for a new index, or when auditing an over-indexed table." metadata: { "includeInPrompt": true }


Database Indexing

Purpose

Turn "this query is slow" into a verified fix. The loop is: measure with EXPLAIN, read the plan, add exactly the index the plan asks for, then prove the fix with a second EXPLAIN. Nothing is added on a hunch.

Workflow

  1. Reproduce and measure. Run the slow query wrapped in EXPLAIN (ANALYZE, BUFFERS). Never guess from the SQL text alone. Read the plan bottom-up: the most indented node executes first. See references/explain-field-guide.md for how each field reads.
  1. Name the bottleneck. Feed the plan text to bin/analyze_plan.py (it flags the common smells) or read it by hand. The usual suspects: a Seq Scan with a large Rows Removed by Filter (rows read, rows thrown away), estimated rows far from actual rows (stale statistics), a Sort node on a hot path, a Nested Loop running thousands of times.
  1. Pick the index that matches. One query pattern, one index:
  1. Create it safely. On a live table use CREATE INDEX CONCURRENTLY so writes are not locked out. Give the index a descriptive name (idx_orders_customer_created) so the next person can tell what it is for.
  1. Prove it. Re-run the same EXPLAIN (ANALYZE, BUFFERS). The plan should show an index scan, Rows Removed by Filter should collapse, and execution time should drop. If the plan did not change, the index was not the fix: drop it and go back to step 2.
  1. Audit regularly. Every index taxes every write. Periodically check for indexes that are never scanned and drop them. PostgreSQL keeps the evidence in pg_stat_user_indexes; the audit queries live in references/explain-field-guide.md.

Output Contract

Operating Rules

  1. Measure before and after, every time. An index added without a before/after comparison is a guess, not a fix.
  2. Index real query patterns, not columns. Unused indexes cost writes and storage for zero benefit.
  3. Never index a column wrapped in a function with a plain index: the planner cannot match WHERE lower(email) = ? to an index on (email). Index the expression.
  4. Respect the trade-off: indexes speed reads and slow writes. On a write-heavy table, add indexes sparingly and confirm the write cost is acceptable.
  5. Do not add an index to fix a stale-statistics problem. If estimated rows and actual rows differ by an order of magnitude, run ANALYZE on the table first.
  6. Small tables do not need indexes: a sequential scan of a table that fits in a few pages is cheaper than index overhead.
  7. Foreign key columns in PostgreSQL are not indexed automatically. Index them when the child table is joined or the parent row is deleted.

Versions

v1.0.02026-10-05 · 0 installs · Ed25519-signed./install.sh database-indexing 1.0.0bundle (.zip)

publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e

Ratings

No ratings yet — be the first to rate it.