Sql optimizer
The largest community-driven library of Agent Skills (SKILL.md + scripts/references/examples) for Claude, Codex, Gemini CLI, Cursor and friends.
npx -y skills add JayRHa/AgentSkills --skill sql-optimizerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Diagnoses and fixes slow SQL queries using EXPLAIN/EXPLAIN ANALYZE plan reading, index design, query rewrites, statistics, and schema-aware tuning across PostgreSQL, MySQL/MariaDB, SQL Server, Oracle, and SQLite. Use this skill when a user says a query is slow, times out, "takes forever", needs an index, asks to "optimize this SQL", "why is this query slow", "read this EXPLAIN plan", "add an index", "reduce query cost", "fix a full table scan / seq scan", "N+1 query", "tune the database", or pastes a query plan and asks what is wrong.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
7.3 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it
SQL Optimizer
Overview
This skill turns "this query is slow" into a concrete, evidence-driven fix. It reads execution plans, identifies the dominant cost, proposes the smallest effective change (index, rewrite, schema, or config), and verifies the improvement with before/after measurements.
Keywords: slow query, EXPLAIN, EXPLAIN ANALYZE, query plan, seq scan, full table scan, index, covering index, composite index, query rewrite, sargable, N+1, timeout, high cost, cardinality, statistics, ANALYZE, query tuning, database performance, PostgreSQL, MySQL, SQL Server, Oracle, SQLite.
Golden rule: measure, change one thing, measure again. Never guess. Never add an index without reading the plan first.
Process
Follow these steps in order. Do not skip step 1 or 2.
-
Gather context. Identify: the engine + version, the exact query (with real-ish parameters, not placeholders), table row counts, existing indexes, and how the query is run (ORM? prepared statement? batch?). If any are missing, ask or inspect the schema. See
references/dialect-cheatsheet.mdfor how to collect each per engine. -
Capture the real plan. Run the engine's analyze form to get actual timing and row counts, not just estimates:
- PostgreSQL:
EXPLAIN (ANALYZE, BUFFERS, VERBOSE, FORMAT TEXT) <query>; - MySQL 8+/MariaDB:
EXPLAIN ANALYZE <query>;(orEXPLAIN FORMAT=JSON) - SQL Server:
SET STATISTICS IO, TIME ON;+ Actual Execution Plan - Oracle:
EXPLAIN PLAN FOR ...; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);thenDBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'ALLSTATS LAST') - SQLite:
EXPLAIN QUERY PLAN <query>;Wrap writes (UPDATE/DELETE) in a transaction you roll back, or test on a SELECT-shaped copy.
- PostgreSQL:
-
Find the dominant cost. Read the plan bottom-up / inner-most-first. Locate the node with the largest
actual time×loops(PostgreSQL) or highest cost/rows. Compare estimated vs actual rows — a large mismatch (>10x) means stale statistics or a bad predicate estimate. Use the diagnosis table inreferences/plan-reading.md. -
Classify the problem into one of these buckets, then apply the matching fix:
- Full/sequential scan on a large table with a selective filter → add/repair an index (step 5).
- Index exists but unused → non-sargable predicate, type mismatch, or wrong column order (step 6).
- Huge row estimate mismatch → refresh statistics (
ANALYZE/UPDATE STATISTICS), then re-plan. - Expensive sort/hash/aggregate spilling to disk → covering/composite index or more work_mem.
- Nested loop with high
loops→ likely N+1 or missing join index; consider batching or a join. - Returning/scanning far more rows than needed → add LIMIT, narrow SELECT list, prefilter.
-
Design indexes deliberately. Apply the column-ordering rules (equality → range → sort → include) in
references/indexing-guide.md. Prefer one well-ordered composite/covering index over many single-column ones. Estimate write/storage cost before recommending. -
Rewrite the query to be sargable and minimal. Remove functions on indexed columns, fix implicit casts, replace
ORwithUNION ALLorINwhere it unlocks an index, turn correlated subqueries into joins, push filters down, and select only needed columns. Patterns are inreferences/rewrite-patterns.md. -
Verify. Re-run the analyze form. Confirm: lower actual total time, scan replaced by index seek/scan, estimate≈actual, no disk spill. Report before/after numbers. If no improvement, revert the change (especially indexes) — do not leave dead indexes behind.
-
Document. Produce a short report: problem, root cause, change made, before/after timing, and any trade-offs (write amplification, storage). Use
templates/optimization-report.md.
Optionally run python3 scripts/explain_analyzer.py plan.json to auto-flag seq scans, row
mis-estimates, and disk spills from a PostgreSQL FORMAT JSON plan.
Decision Framework: which lever to pull
- Cheapest first. Statistics refresh (free, instant) → query rewrite (no schema change) →
index (write cost) → schema change (migration) → config (
work_mem, etc., affects everyone). - Selectivity test. An index helps only if the predicate returns a small fraction of rows (rule of thumb: < ~5-10% for a non-covering index). For low-selectivity filters a scan is correct.
- Read vs write balance. Every index slows INSERT/UPDATE/DELETE and costs storage. On write-heavy tables, justify each index.
- One change at a time. Bundling changes makes attribution impossible.
Best Practices
- Always test with realistic parameter values and on data volumes close to production.
- Prefer
EXPLAIN ANALYZE(actuals) over plainEXPLAIN(estimates) when safe to execute. - Make predicates sargable:
WHERE col = ?notWHERE fn(col) = ?; range on dates notYEAR(col). - Order composite index columns: equality predicates first, then the range/sort column.
- Use covering indexes (INCLUDE / extra key columns) to enable index-only scans on hot queries.
- Keep the SELECT list narrow; avoid
SELECT *in hot paths. - Refresh statistics after big data loads before blaming the planner.
- For ORMs, look for N+1: one query per row in a loop → use eager loading / a single join.
- Name indexes meaningfully and record why they exist.
Common Pitfalls
- Adding an index without reading the plan — it may never be used or may not help.
- Trusting estimated rows when actuals differ wildly (stale stats).
- Wrapping an indexed column in a function or casting it, killing index use.
- Leading-column violation: a composite index
(a,b)cannot serve a query filtering only onb. - Over-indexing: many redundant indexes crush write throughput.
ORacross different columns preventing index use (rewrite toUNION ALL).- Optimizing a query that runs once instead of the one that runs millions of times — profile first.
- Testing on tiny dev data where every plan looks fine; scans only hurt at scale.
- Forgetting parameter sniffing / plan caching differences between literal and bound values.
Bundled Files
references/plan-reading.md— how to read each engine's plan, node-by-node diagnosis table.references/indexing-guide.md— index types, column ordering, covering indexes, selectivity.references/rewrite-patterns.md— before/after sargable rewrites and anti-patterns.references/dialect-cheatsheet.md— per-engine commands to collect plans, stats, and metadata.scripts/explain_analyzer.py— flags problems in a PostgreSQL JSON plan (stdlib only).examples/slow-query-walkthrough.md— a full worked diagnosis from plan to verified fix.templates/optimization-report.md— fill-in report template for handing off the result.
What ships with it: 7 files
22.8 KB alongside SKILL.md, 1 of them executable
examples/
references/
- dialect-cheatsheet.md2.6 KB
- indexing-guide.md3.4 KB
- plan-reading.md3.7 KB
- rewrite-patterns.md3.4 KB
scripts/
- explain_analyzer.pyruns5.4 KB
templates/
- optimization-report.md1.6 KB
Gives 0 of the 12 instructions most databases sql skills give in ~1.6k tokens
Counted across 589 of the 662 authors here whose files we hold, read 2026-08-07
- Use parameterized queriesin 37 of 589, across 34 files
- Use timestamptz for timestampsin 30 of 589, across 14 files
- Index foreign keysin 29 of 589, across 18 files
- Create indexes concurrentlyin 29 of 589, across 24 files
- Use numeric type for moneyin 25 of 589, across 8 files
- Use cursor pagination instead of offsetin 24 of 589, across 17 files
- Select only required columnsin 24 of 589, across 20 files
- Add indexes manually on foreign key columnsin 22 of 589, across 12 files
- Normalize to third normal formin 19 of 589, across 10 files
- Configure connection poolingin 19 of 589, across 17 files
- Put equality columns before range columns in indexesin 18 of 589, across 10 files
- Read individual rule files for detailed explanationsin 18 of 589, across 4 files
Said here and by no other author read
- Gather context including engine version and query
- Capture the actual execution plan
- Read the plan to find the dominant cost
- Change one thing at a time
- Design indexes deliberately using column-ordering rules
- Rewrite the query to be sargable and minimal
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.