An LLM can read an EXPLAIN plan, suggest an index, and rewrite a query in
seconds — and it can also confidently suggest an index that doesn’t help,
invent an EXPLAIN line that doesn’t exist in your engine’s output, or
“optimize” a query into one that returns different results. This lesson is
not about whether to use AI assistance for query tuning — it’s about the
specific, mandatory validation workflow that makes AI assistance safe to
use in a codebase this handbook expects to run in production. Every
technique here treats the model’s output the way this handbook treats a junior
engineer’s first draft: a starting hypothesis to verify, not a conclusion
to trust.
Schema note: this lesson’s SQL lab uses the handbook’s shared
transactionstable (part of00_Schema.sql), the module’s documented extension to the coreemployes/departments/locationsschema.
EXPLAIN analysis instead
of generic, hallucination-prone adviceThe failure mode this lesson addresses isn’t “the AI gave a bad answer” — it’s “the AI gave a plausible-sounding, syntactically valid, wrong answer, and it shipped because nobody validated it the way they’d validate a human’s suggestion.” An LLM has no execution environment by default; it is pattern-completing what a correct-looking answer resembles, not running your query against your data. Every technique in this lesson exists to close that specific gap.
The single highest-leverage habit: paste the actual EXPLAIN output,
not a description of the problem. “My query is slow” produces generic
advice. A pasted plan with row-count estimates, join types, and index names
produces analysis the model can ground in specifics instead of guessing.
EXPLAIN
(ANALYZE, BUFFERS) output” scopes the model to syntax and planner
behavior that actually exists in your environment.CREATE TABLE + existing indexes), not just the
query. A model without the schema will invent plausible-sounding column
names or suggest an index that duplicates one that already exists.EXPLAIN
numbers, produces output you can check against this handbook’s own
vocabulary (SARGability, cardinality misestimate, etc.) line by line. A
model asked only for the fix skips the step where you could have caught
a wrong premise.Never create an AI-suggested index directly. Run it through the same checklist you’d apply to a human’s suggestion, using Lesson 03 as the ground truth:
EXPLAIN after creating the index in a non-production
environment, exactly as you would for a human-suggested index. The AI
suggested it; the query planner decides whether it’s used.Cross-check every AI-suggested rewrite against
PERFORMANCE_SMELLS.md (and this handbook’s COST_SMELLS.md, Lesson 10) in
both directions:
NULL handling and ordering where the
query depends on it) before considering plan-shape improvement relevant
at all. A faster query that returns different rows is not an
optimization — it’s a bug the model introduced with high confidence.| Red flag | Why it happens | What to do |
|---|---|---|
A cited EXPLAIN field or plan-node name that doesn’t exist in your engine/version |
Models blend syntax and output formats across Postgres, MySQL, SQL Server, and older engine versions | Cross-check every cited field name against your actual EXPLAIN output before trusting the analysis built on it |
| A suggested index that the model claims will be used, stated with certainty | The model cannot run your query planner; it is predicting, not observing | Never treat a model’s plan-usage claim as verified — only your own EXPLAIN run against the real schema and data volume confirms it |
| Specific performance numbers (“this will be 10x faster”) with no measurement behind them | Precise-sounding numbers are a known confidence-inflation pattern separate from actual accuracy | Treat any unmeasured numeric claim as illustrative at best; benchmark it yourself (Lesson 11) before repeating the number anywhere |
A rewrite that changes aggregation, JOIN type, or NULL-handling semantics while claiming “identical results” |
Semantic-preservation is exactly the kind of subtle correctness property a model can get wrong while sounding confident | Always diff the actual result sets — see “Rewrite Verification” above; never accept a semantic-equivalence claim without checking it |
| Confident engine-specific syntax for a feature that doesn’t exist in your engine or version | Training data blends across engines and versions without a reliable boundary | Check the suggested syntax against your engine’s actual current documentation before running it anywhere near production |
1. EXPLAIN plan analysis (grounded, not generic)
I'm running [ENGINE + VERSION, e.g. "PostgreSQL 16"]. Here is my schema:
[PASTE CREATE TABLE + existing indexes]
Here is my query and its EXPLAIN (ANALYZE, BUFFERS) output:
[PASTE QUERY]
[PASTE EXPLAIN OUTPUT]
Walk through the plan node by node. For each node, tell me what it's doing
and whether the estimated vs. actual row counts suggest a cardinality
misestimate. Do not suggest a fix yet -- I want your diagnosis first.
2. Index suggestion with mandatory tradeoff disclosure
Given this schema and query [PASTE], suggest an index that would help.
For your suggestion, explicitly state:
1. The exact column order and why that order matters for this query
2. Whether an existing index already partially covers this
3. The write-side cost (INSERT/UPDATE/DELETE overhead) of adding it
4. One scenario where this index would NOT be chosen by the planner
3. Rewrite with correctness-preservation proof
Here is a query I want to optimize: [PASTE]
Propose a rewrite. Then, separately, write a verification query I can run
that proves the original and rewritten queries return identical result
sets (same rows, same order if order matters, same NULL handling) against
my actual data -- not just an argument for why they should be equivalent.
4. Adversarial self-check (“what would make this wrong”)
You suggested [PASTE THE MODEL'S PRIOR SUGGESTION].
Before I implement this: what assumption about my data distribution,
cardinality, or engine version would make this suggestion NOT help, or
actively make performance worse? Be specific, not generic.
5. Cross-check against a known smell catalog
Here is a catalog of performance anti-patterns my team maintains:
[PASTE RELEVANT ENTRIES FROM PERFORMANCE_SMELLS.md / COST_SMELLS.md]
Here is a query and a proposed rewrite: [PASTE BOTH]
Does the rewrite eliminate any smell in this catalog? Does it introduce
any smell in this catalog that the original didn't have? Answer both
questions explicitly, referencing specific catalog entries.
No AI-assisted tuning output reaches production without all of the following, regardless of how confident the model’s response sounded:
EXPLAIN re-run against the real schema, on a non-production
environment, by a human — not accepted from the model’s claimPERFORMANCE_SMELLS.md / COST_SMELLS.md in both
directions (smell eliminated, no new smell introduced)EXPLAIN ANALYZE output or
summary statistics directly.EXPLAIN
terminology given its prevalence in training data, but still verify any
cited planner behavior (e.g., specific costing constants) against your
actual postgresql.conf settings, which vary by deployment.OPTION, query hints,
index hints) against your actual SQL Server / Azure SQL version — hint
availability and behavior has changed across versions, and a
hallucinated hint can fail silently rather than erroring.EXPLAIN output, then trusting
a suggestion that was necessarily generic given what it was givenEXPLAIN check confirming the planner actually uses itEXPLAIN context, then being surprised the fix doesn’t workEXPLAIN) independently of whether you find
the model’s stated reasoning convincing.EXPLAIN for the
planner’s actual cost comparison between the new index and its existing
choice — the suggestion may be technically valid but genuinely not
selective enough at your real data’s cardinality.NULL handling and join-type changes first; this is the most
common category of AI-introduced correctness regression per this
module’s “Red Flags” table.AI-assisted tuning suggestions are generated without knowledge of how your data will grow. A suggestion validated as correct and beneficial against today’s data volume still needs the same re-validation-over-time treatment Lesson 11 applies to every other performance-relevant change — an AI-suggested index that helped at 100K rows is not guaranteed to still be the right index at 100M rows, and nothing about the AI-assisted origin of that index makes it exempt from Lesson 11’s CI gate or this handbook’s ongoing tuning workflow.
/*+ ... */)
are a particularly high-risk category to accept unverified — Oracle hint
syntax is extensive, version-specific, and a subtly wrong hint can
silently fail to apply rather than erroring, exactly the “hallucinated
hint” failure mode described above generalized to Oracle’s specific
hint dialect.EXPLAIN
output can suggest analysis techniques (buffer cache hit ratios,
concurrent-session locking behavior) that don’t apply to SQLite’s
embedded, single-writer model — verify any suggestion is actually
meaningful for an embedded engine before applying it.EXPLAIN ANALYZE output rather
than assuming general SQL-engine advice transfers cleanly.EXPLAIN review but
changes the result set. How would your validation process have caught
this before merge?”AI assistance genuinely accelerates the hypothesis-generation stage of
query tuning — it does not accelerate, and should never replace, the
verification stage this handbook has taught as mandatory from the start.
Treat every AI-suggested index, rewrite, or diagnosis as an unverified
claim from a fluent, occasionally wrong source, and route it through the
same EXPLAIN-and-benchmark discipline you’d apply to a suggestion from
any other engineer — confident tone included.
PERFORMANCE_SMELLS.mdCOST_SMELLS.md