What this checks
Paste a query and this reads its WHERE, JOIN ON, ORDER BY, and GROUP BY clauses to suggest a candidate composite index per table — before you've run the query against real data at all. Columns compared with = or IN are treated as equality filters and placed first in the suggested column order; a range condition (>, <, BETWEEN, a prefix LIKE 'foo%') is placed after them, since a standard B-tree index can satisfy any number of leading equality predicates but only one range predicate efficiently; ORDER BY/GROUP BY columns not already covered get appended last, so the same index can also avoid a separate sort step.
Predicates that a standard index generally can't help with — a leading wildcard LIKE '%foo', a column wrapped in a function like LOWER(email) = ..., !=/<>, and a bare IS [NOT] NULL — are called out separately with the reason, rather than silently omitted.
What it doesn't do
This is static analysis of the query text — it has no row counts, no data distribution, no idea how selective a column actually is, and no connection to any real database. Real index decisions depend on all of that. Treat every suggestion here as a candidate worth testing, not a verdict: run EXPLAIN ANALYZE before and after adding an index and confirm the planner actually picks it up and the query gets faster — SQL Explain Helper reads that real, executed plan and points at the actual bottleneck, which is the diagnostic this tool's predictions should be checked against.
It also doesn't know what indexes already exist. If a suggested index duplicates an existing primary key, unique constraint, or another index, it's redundant — check SQL Diff or your database's own catalog before creating anything. And it only looks at a single query in isolation: a real indexing decision should weigh every query that touches a table, not just one, since every index also has a write-time cost on every insert and update.
Multiple OR-ed conditions at the top level of a WHERE clause are a genuinely harder case — a single composite index rarely helps all branches equally, so this tool only analyzes the first branch and flags the rest rather than guessing. Old-style comma-separated FROM a, b table lists are recognized well enough to detect ambiguous unqualified columns, but explicit JOIN syntax parses more reliably.
FAQ
Why does column order in the suggested index matter?
A composite index is a single sorted structure, sorted by its first column, then its second within each value of the first, and so on — like a phone book sorted by last name, then first name. That ordering is exactly why equality columns belong first: the index can jump straight to the matching last name (and then the matching first name) instantly. A range condition breaks that jump — once you need "everyone with last name Smith and a first name after M," the index can narrow to Smith and then scan forward, but nothing after that range column stays sorted in a way the index can use for further filtering.
Should I create every suggested index?
Not automatically. Each index speeds up the queries it matches but slows down every INSERT/UPDATE/DELETE on that table a little, and takes disk space. A handful of well-chosen composite indexes covering your actual hot queries beats one index per query you've ever written.
Does this work for MySQL and SQL Server, or just PostgreSQL?
The equality-then-range column-ordering heuristic and the B-tree limitations it's based on apply broadly across PostgreSQL, MySQL (InnoDB), and SQL Server — they all build on the same underlying B-tree index structure. The generated CREATE INDEX syntax shown is deliberately plain and works unmodified on all three.