sql-query-optimizer
Skill0 starsChanged 6 months agoMITView on GitHub
Diagnoses slow SQL queries and recommends concrete fixes — indexes, query rewrites, and schema changes. Reads EXPLAIN/EXPLAIN ANALYZE plans for PostgreSQL, MySQL, SQLite, and SQL Server. Use when a query is slow, a database is under load, the user shares an execution plan, or asks to optimize, tune, or speed up SQL.
6 other projects use a version of this.
Adopted by
Most recently taken up by
- nek1987/auto-agent-harnesstheir own version, first seen Oct 11, 2026
- CreativeActtech/llm-skillstheir own version, first seen Oct 8, 2026
- SkillMedev/data-engineering-pipelinetheir own version, first seen Oct 5, 2026
- myclaude-sh/sql-query-optimizertheir own version, first seen Aug 26, 2026
- mDevsLabs/Skillstheir own version, first seen Jul 29, 2026
- Nikoxkx/Agent-Skillstheir own version, first seen Jun 8, 2026
Other versions6 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 6
- nek1987/auto-agent-harness★ 4same name
- CreativeActtech/llm-skills★ 2same name
- mDevsLabs/Skills★ 2same name
- Nikoxkx/Agent-Skills★ 1same name
- myclaude-sh/sql-query-optimizer★ 0same name
- SkillMedev/data-engineering-pipeline★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository11 other files it gives its agents.
- a11y-auditorSkill
- api-design-reviewerSkill
- changelog-writerSkill
- conventional-commit-writerSkill
- dockerfile-hardenerSkill
- env-secrets-auditorSkill
- error-message-explainerSkill
- pr-description-writerSkill
- readme-generatorSkill
- regex-builderSkill
- test-writerSkill
The file
We split this skill into the rules it gives an agent
7 rules. 0 are common, 4 are distinctive, and 3 are very specific to this project.
0
Common
Most of the 5 edited versions we read keep these.
4
Distinctive
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 28
Ask for or run the analyzed plan so you see actual rows and time, not just estimates:
- Distinctive: line 35
If you only have the query, reason from the schema and predicates but say the estimate is unverified until a plan is captured.
- Distinctive: line 83
Prefer a covering index (include the selected columns) so the query is index-only and never touches the heap:
- Distinctive: line 91
Use a partial index when you only ever query a slice of the table:
- Very specific: line 115
If the application loops issuing one query per row, collapse it into a single JOIN or an IN (...) / = ANY(...) batch.
- Very specific: line 131
Verify: re-run EXPLAIN ANALYZE.
- Very specific: line 136
Write-heavy tables: every index slows INSERT/UPDATE/DELETE.
“Common” is measured: kept by at least 6 in 10 of the 5 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
SQL Query Optimizer
Turn a slow query into a fast one with evidence-based changes. Always measure first, change one thing at a time, and re-measure.
Workflow
- [ ] 1. Capture the plan (EXPLAIN ANALYZE) and the slowest operators
- [ ] 2. Identify the dominant cost (scan, sort, join, or row estimate error)
- [ ] 3. Form one hypothesis and the smallest change that tests it
- [ ] 4. Recommend the change with the expected effect
- [ ] 5. State how to verify (re-run plan, compare actual time/rows)Step 1 — Get the real plan, not the estimate
Ask for or run the analyzed plan so you see actual rows and time, not just estimates:
- PostgreSQL:
EXPLAIN (ANALYZE, BUFFERS, VERBOSE) <query>; - MySQL 8+:
EXPLAIN ANALYZE <query>;(orEXPLAIN FORMAT=JSON) - SQLite:
EXPLAIN QUERY PLAN <query>; - SQL Server: enable "Include Actual Execution Plan", or
SET STATISTICS IO, TIME ON;
If you only have the query, reason from the schema and predicates but say the estimate is unverified until a plan is captured.
Step 2 — Read the plan top-down, fix bottom-up
Find the operator that consumes the most actual time, and check the row-estimate accuracy (estimated vs actual rows). A large gap (e.g. estimate 10, actual 1,000,000) means stale statistics or a non-sargable predicate is misleading the planner.
| Signal in the plan | Likely cause | First thing to try |
Seq Scan / Full Table Scan on a large table with a selective WHERE | Missing index | Add an index on the filter/join columns |
| Estimated rows ≪ actual rows | Stale statistics | ANALYZE table; (PG) / ANALYZE TABLE (MySQL) / UPDATE STATISTICS (MSSQL) |
| Index exists but unused | Non-sargable predicate (function/cast on the column) | Rewrite so the column is bare on one side |
Expensive Sort / Hash spilling to disk | ORDER BY / GROUP BY / large hash join | Covering/sorted index, or raise work_mem |
Nested Loop over many rows | Bad join order from wrong estimates | Refresh stats; consider a hash/merge join |
| Same subquery evaluated per row | Correlated subquery | Rewrite as a JOIN or window function |
Step 3 — The highest-impact fixes (in order)
1. Make predicates sargable (index-usable)
A predicate is sargable when the indexed column appears bare on one side. Wrapping it in a function or applying a math/cast prevents index use.
-- Not sargable: function on the column blocks the index
WHERE DATE(created_at) = '2026-05-22'
WHERE LOWER(email) = 'a@b.com'
WHERE price * 1.2 > 100
-- Sargable: column stays bare; transform the constant or add an expression index
WHERE created_at >= '2026-05-22' AND created_at < '2026-05-23'
WHERE email = 'a@b.com' -- or add an index on LOWER(email)
WHERE price > 100 / 1.22. Add the right index — order matters
For a composite index, put equality columns first, then the range/sort column. An index
on (status, created_at) serves WHERE status = 'open' ORDER BY created_at; reversing the
columns does not.
-- Query: WHERE status = 'open' AND created_at > now() - interval '7 days'
CREATE INDEX idx_orders_status_created ON orders (status, created_at);Prefer a covering index (include the selected columns) so the query is index-only and never touches the heap:
-- PostgreSQL
CREATE INDEX idx_orders_lookup ON orders (status, created_at) INCLUDE (total, customer_id);Use a partial index when you only ever query a slice of the table:
CREATE INDEX idx_active_users ON users (last_login) WHERE deleted_at IS NULL;3. Avoid SELECT *
Select only the columns you need. It reduces I/O and makes covering indexes possible.
4. Replace OFFSET pagination with keyset (seek) pagination
OFFSET 100000 still reads and discards 100,000 rows. Page by the last seen key instead:
-- Slow on deep pages
SELECT * FROM events ORDER BY id LIMIT 20 OFFSET 100000;
-- Keyset: O(log n) regardless of page depth
SELECT * FROM events WHERE id > :last_id ORDER BY id LIMIT 20;5. Fix N+1 query patterns
If the application loops issuing one query per row, collapse it into a single JOIN or an
IN (...) / = ANY(...) batch. This is usually the single biggest application-level win.
Examples
Input: SELECT * FROM orders WHERE YEAR(created_at) = 2026; is slow.
Output:
- Cause:
YEAR(created_at)is non-sargable, forcing a full scan. - Fix: rewrite as a half-open range and index the column.
CREATE INDEX idx_orders_created ON orders (created_at); SELECT id, customer_id, total FROM orders WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01'; - Verify: re-run
EXPLAIN ANALYZE; expect an Index Range Scan and far fewer rows read.
Common edge cases
- Tiny tables: a sequential scan can be faster than an index; don't add indexes blindly.
- Write-heavy tables: every index slows
INSERT/UPDATE/DELETE; justify each one. - Low-cardinality columns (e.g. boolean
is_active): a plain b-tree index rarely helps; consider a partial index on the rare value instead. ORacross different columns: can defeat indexes; aUNION ALLof two indexed queries is often faster.- Parameter sniffing (SQL Server): one plan cached for skewed parameters can be slow for
others; consider
OPTION (RECOMPILE)or optimizing for a typical value.
Additional resources
- For a fuller catalog of anti-patterns and engine-specific notes, see references/anti-patterns.md.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

