Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rule catalog

Rules turn plan data into findings. Every finding names its rule, the node it is about, a severity, the evidence that triggered it, and a suggested action. The bar for a rule is precision: a rule that is sometimes obviously wrong does more harm than a missing rule. So each rule also says when it deliberately stays silent.

The index advisor builds its CREATE INDEX suggestions on the findings of ES001, ES005, ES006 and ES009 (see “Index advisor” in ARCHITECTURE.md).

Each rule lives in its own file, crates/explainsql-core/src/rules/esNNN_*.rs, with its thresholds as named constants; they will become configurable. Every plan in the fixture corpus is checked against the rules its scenario expects, and no other rule may fire (see fixtures/README.md). Each rule has a page with its thresholds, when it stays silent, and an example from the corpus. To propose a new rule, see contributing.

Severity follows the share of the runtime involved: half or more is high, a fifth or more is medium, anything less is low. When the plan has no timing, the share is taken from buffers. Misestimates are low on their own and at least medium when they feed a join.

Shares are exclusive: the time spent in a node itself, as a fraction of the statement’s execution time. See “Metrics” in ARCHITECTURE.md for how parallel workers, CTEs, InitPlans and rounding are accounted for.

IDNameSuggested action
ES001Selective sequential scanAn index on the filtered columns, or rewriting a condition that wraps the column
ES002Row misestimateANALYZE, CREATE STATISTICS, statistics target
ES003Sort spilled to diskA work_mem for the statement, with what it may take, or an index matching the sort
ES004Hash or aggregate spilled to diskA work_mem for the statement, with what it may take, or hash_mem_multiplier
ES005Expensive nested-loop inner sideIndex on the inner join key
ES006Index scan that filters most rowsComposite index
ES007Index-only scan with many heap fetchesVACUUM (visibility map)
ES008Lossy bitmap or heavy recheckwork_mem
ES009Slow foreign-key triggerIndex on the referencing columns
ES010Cartesian productAdd the missing join condition
ES011Fewer parallel workers than plannedReview the parallel worker pool
ES012JIT overhead dominatesjit_above_cost, or jit = off for OLTP
ES013Planner settings force the planReset enable_* settings left off in the session, role or database