SQL Query Optimization Tool
This free online SQL query optimizer analyzes your query in the browser and returns index suggestions, rewritten SQL, and full table scan detection. Paste your SQL — no signup, and your query never leaves your device.
Advanced: CREATE TABLE DDL (optional)
Issues Found
Your Query: Before & After
Before (your SQL)
—
After (rewritten)
Index Suggestions
How It Works
- Paste your SQL — the query you want to speed up.
- Dialect — auto-detected by default; you can force MySQL, PostgreSQL, SQLite, DuckDB, SQL Server, or Oracle. The analysis and index advice adapt to the engine.
- Results update live — the tool parses your SQL into an AST in your browser as you type and flags slow patterns, then gives you rewritten SQL and index suggestions.
- Optional: paste CREATE TABLE DDL in the Advanced section to enable SELECT * expansion and column-aware index names.
Supported Rules
- SELECT * — expanded to explicit columns when DDL is provided, or flagged as a warning otherwise.
- Function on an indexed column —
YEAR(created_at),UPPER(name), etc. are non-sargable and prevent index use. - LIKE with a leading wildcard —
LIKE '%term'forces a full table scan. - IN (SELECT ...) / correlated subqueries — rewritten toward JOIN or EXISTS.
- Large OFFSET — flagged for keyset pagination.
- Missing WHERE — on SELECT, UPDATE, or DELETE.
- OR conditions — noted for index-merge or UNION rewriting.
- Implicit type conversion — comparing a numeric column to a string literal, and similar heuristics.
Examples: 4 Slow Queries Rewritten
Four reference examples of the slow patterns this optimizer catches most often, each with the rewrite and the index that fixes it. These are static examples — your own query's before-and-after comparison appears in the tool above.
1. Function wraps an indexed column
Before
SELECT id, total FROM orders WHERE YEAR(created_at) = 2024;
After
SELECT id, total FROM orders WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01'; CREATE INDEX idx_orders_created_at ON orders (created_at);
Wrapping the column in YEAR() hides it from the B-tree, so the index can't seek. Compare the raw column against a range instead and the index is used.
2. LIKE with a leading wildcard
Before
SELECT id, email FROM users WHERE email LIKE '%@gmail.com';
After
ALTER TABLE users ADD COLUMN email_domain VARCHAR(255) AS (SUBSTRING_INDEX(email, '@', -1)) STORED; CREATE INDEX idx_users_email_domain ON users (email_domain); SELECT id, email FROM users WHERE email_domain = 'gmail.com';
A leading % means the B-tree index can't be used. Add a generated column and query it with equality, or use a full-text index.
3. IN (SELECT …) subquery
Before
SELECT * FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE status = 'active');
After
SELECT o.id, o.customer_id, o.total, o.created_at FROM orders o JOIN customers c ON c.id = o.customer_id WHERE c.status = 'active'; CREATE INDEX idx_customers_status_id ON customers (status, id); CREATE INDEX idx_orders_customer_id ON orders (customer_id);
Rewrite as a JOIN (which also removes the SELECT *), then index the join and filter columns on both sides.
4. Large OFFSET pagination
Before
SELECT id, total FROM orders ORDER BY created_at DESC LIMIT 20 OFFSET 1000;
After
-- use the previous page's last created_at as the cursor SELECT id, total FROM orders WHERE created_at < '2024-06-01 12:00:00' ORDER BY created_at DESC LIMIT 20; CREATE INDEX idx_orders_created_at_desc ON orders (created_at DESC, id);
The larger the OFFSET, the more rows the database must scan and discard. Keyset (cursor) pagination keeps every page on the index.
Dialect Notes
| Dialect | Index advice focus |
|---|---|
| MySQL | B-tree indexes; composite indexes follow the leftmost-prefix rule. |
| PostgreSQL | Partial indexes, GIN for jsonb, BRIN for large time-series tables. |
| SQLite | Basic B-tree indexes; a single index per query path is usually enough. |
| DuckDB | Columnar engine — avoid SELECT *, prefer narrow scans, and leverage Parquet partitioning. |
| SQL Server | B-tree indexes; watch for non-sargable functions and implicit conversions. |
| Oracle | B-tree indexes; avoid wrapping indexed columns in functions, and watch for implicit conversions. Parsed with the closest available grammar. |
Frequently Asked Questions
How can I optimize a SQL query online for free without signing up?
Paste your query into this free online SQL optimization tool — the dialect is auto-detected, or you can pick it manually — and the results update as you type. It runs entirely in your browser and flags full table scans, non-sargable predicates, SELECT *, missing WHERE clauses, and more — with index suggestions and rewritten SQL.
How do I detect a full table scan in MySQL without connecting to the database?
Paste your query and the tool inspects the parsed SQL for full-table-scan patterns such as LIKE with a leading wildcard, functions wrapped around indexed columns, or missing WHERE clauses. Static analysis catches most access-path problems before you ever need to run EXPLAIN.
Will this tool upload my SQL to a server?
No. All parsing and analysis happens locally in your browser using JavaScript. Your SQL never leaves your device and is never sent to any server.
Can it create indexes automatically?
No — it does not connect to your database. It suggests CREATE INDEX statements based on your query's WHERE and JOIN columns, and you run them yourself.
Does it support DuckDB or SQLite?
Yes. The dialect selector covers MySQL, PostgreSQL, SQLite, DuckDB, SQL Server, and Oracle, and the advice adjusts per engine — columnar-friendly guidance for DuckDB, basic B-tree guidance for SQLite, and ANSI-generic index advice for SQL Server and Oracle.
What SQL patterns does this optimizer detect?
The optimizer flags SELECT *, functions wrapping indexed columns (YEAR, UPPER, EXTRACT, CAST), LIKE '%…', IN (SELECT …) subqueries, large OFFSET pagination, missing WHERE clauses, OR conditions that block single-index use, and implicit type conversions.
Do I need to run EXPLAIN first?
No. The tool works entirely from the SQL text — it parses your query into an AST and analyzes the access-path implications without a database connection. If you already have EXPLAIN output, keep it handy to sanity-check the tool's suggestions against your real execution plan.
How do I fix a slow SQL query?
Start with the three things that cause most slow queries: a predicate the index can't use (a function wrapped around an indexed column, or LIKE '%term'), a filter or join column with no index at all, and paging deep with a large OFFSET. Paste the query above and the tool flags all three, then hands you a rewritten query and the CREATE INDEX statements to run.
What is the best SQL query optimization tool?
If you want analysis against your live execution plan, server-side tools such as EverSQL and SQLAI.ai connect to your database and read EXPLAIN output (they're paid). If your concern is that you can't upload a query to someone else's server, this page is the answer: it parses and analyzes entirely in your browser, for free, with no signup. For most non-sargable predicates, bad join shapes, and missing indexes, static analysis already tells you what to fix.
Is there a free SQL query optimizer that doesn't upload my query?
Yes — this one. Parsing and rule checking run in JavaScript on your machine; the SQL text is never sent anywhere. You can verify it: open DevTools → Network, paste a query, and watch for outgoing requests (there are none for the analysis). That's why it also works with proprietary schemas and production queries you're not allowed to paste into a cloud service.
Can it optimize SQL Server or Oracle queries?
Yes — both SQL Server and Oracle are selectable dialects. SQL Server uses its own grammar; Oracle is parsed with the closest available grammar and gets ANSI-generic index advice. The eight rules apply to both just as well — a function wrapping an indexed column or a missing index is slow on every engine. Treat the index suggestions as engine-neutral guidance and confirm the exact syntax on your engine.