~/aiskills402AISKILLS402

SQL Query Optimizer for D1, SQLite and Turso

SQL Query Optimizer for D1, SQLite and Turso is a tested SKILL.md that reviews SQL queries, schemas and migrations for SQLite, Cloudflare D1 and Turso, where the bill and the speed follow the rows a query READS, not the rows it returns; an agent buys it once for $0.01 over x402.

$0.01once · USDC on Base

Price as loaded on this page. The 402 response your agent receives is authoritative.

Tested 2026-10-03No code, no hidden instructionsv1.0.0 · 9.8 KB · perpetual license

Use it when

Reviews SQL queries, schemas and migrations for SQLite, Cloudflare D1 and Turso, where the bill and the speed follow the rows a query READS, not the rows it returns. Finds full scans hidden behind LIMIT, aggregates over growing tables, index column gaps, NOT IN, OR, functions and LIKE patterns that switch an index off, OFFSET pagination, N+1 loops, the D1 limit of 100 bound parameters, tables that never shrink and new flag columns that turn the whole history into pending work; ranks them by cost and gives the index or rewrite that fixes each. Use when asked to optimize a SQL query, review a database schema or a migration, find a slow query, or cut rows read on D1, SQLite or Turso.

Not for

PostgreSQL or MySQL tuning, where the planner and the costs differ, though many patterns carry over; running or timing your queries; choosing a database. It reads the SQL you paste, so anything that depends on data it was not shown, such as real table sizes, is stated as an assumption.

Tested, honestly

Tested 2026-10-03 with a strong and a weak model.

SonnetStrong model, claude-sonnet-5-5
Named the planted problem with the right code in all 11 cases that had one and answered 'No findings.' for the clean schema. Its fixes were working SQL: an index on (scope, created_at) for the gap, a partial index on status = 'pending' for the empty poll, a range on the raw timestamp, keyset pagination, chunks of 50 for D1's 100-parameter limit, a backfill in the same migration, the partial index's WHERE copied into ON CONFLICT. At first 2 of 12 were scored as failures because our pattern accepted only one of the two fixes the skill names; Sonnet chose the other (a latest-prices table kept by the writer; day bounds computed in SQL), both were confirmed with EXPLAIN QUERY PLAN, and the same answers rescored at 12 of 12.
HaikuWeak model, claude-haiku-4-5-20251001
Found the planted problem with the right code and a working fix in all 11 cases that had one, including the Bulgarian request. On the clean schema it invented a finding under a code of its own and proposed DELETE ... LIMIT, which standard SQLite rejects as a syntax error. With Haiku, run any suggested statement before relying on it.

Full test summary

Example

Our own test text, before and after the skill ran. Excerpts only.

English · claude-sonnet-5-5

Before

Schema: CREATE TABLE events (id INTEGER PRIMARY KEY, scope TEXT NOT NULL, symbol TEXT NOT NULL, created_at INTEGER NOT NULL, payload TEXT); CREATE INDEX idx_events ON events(scope, symbol, created_at); The table has about 2 million rows; 90% of them have scope = 'market'. Old rows are deleted after 30 days. Runs every 30 seconds: SELECT * FROM events WHERE scope = 'market' AND created_at > ?…

After

[INDEX-GAP] `SELECT * FROM events WHERE scope = 'market' AND created_at > ? ORDER BY created_at DESC LIMIT 50` Reads: the index `(scope, symbol, created_at)` is searched by `scope` only, because `symbol` has no condition. That means every `market` row still inside the 30-day window is read (about 1.8M at 90% of 2M), then sorted in a temp B-tree before LIMIT 50 applies.…

Bulgarian · claude-sonnet-5-5

Before

Schema: CREATE TABLE jobs (id INTEGER PRIMARY KEY, status TEXT NOT NULL, run_at INTEGER NOT NULL, payload TEXT); The table keeps every job ever run (about 300,000 rows, 'done' or 'failed'). New jobs arrive a few times a day. A worker polls every minute; most polls find nothing: SELECT * FROM jobs WHERE status = 'pending' AND run_at <= ? ORDER BY run_at LIMIT 90;

After

**[EMPTY-PATH]** `SELECT * FROM jobs WHERE status = 'pending' AND run_at <= ? ORDER BY run_at LIMIT 90` Reads: цялата таблица `jobs` (~300 000 реда) при всяко пускане на worker-а. Заявката няма индекс освен първичния ключ. Когато няма чакащи задачи, LIMIT никога не се достига и заявката прочита всички редове.…

What is in the file

  • Hard rules
  • Finding codes
  • Report format
  • Work in this order
  • Short example

Languages

English, Bulgarian. Tried in: English, Bulgarian.

How to buy

Any x402 client works. Without a payment header the endpoint answers 402 and tells your agent what it costs. Sign it, repeat the request with PAYMENT-SIGNATURE, and the file comes back.

Agent (HTTP)

bash
curl -i https://api.aiskills402.com/v1/skills/sql-query-optimizer/file

Agent (MCP)

Connect https://mcp.aiskills402.com/mcp, then use the free tools get_skill (card and payment requirements) and redownload_skill. The payment itself goes over HTTP.

I am a person

Honestly: you need an agent with a USDC wallet, or a small script, plus the x402-buyer skill. There is no card checkout yet. The steps are in the docs.

The file

Version
1.0.0
Payment
x402 · USDC · base
Updates
free, new versions included
Size
9.8 KB (10077 bytes)
SHA-256
09a9cd1326ed96725c5c9da3fe6c5909ff35ccacd113a0a60939bc6b0ba874f5
Updated
2026-10-03

License

Perpetual, non-exclusive; use and modify for yourself incl. paid work; no resale or republishing. Holder: Georgi Kalchev, aiskills402.com. Full terms.

Versions

Current version 1.0.0, updated 2026-10-03. Whoever bought an earlier version gets new ones free through the same re-download token.

  1. v1.0.0 · 2026-10-03

    First release: reviews SQL, schemas and migrations for SQLite, Cloudflare D1 and Turso by rows read; fifteen finding codes, each with a concrete index or rewrite, ranked by cost, with a way to verify the fix.

FAQ

Does it work for PostgreSQL?

It is written for SQLite and the services built on it, Cloudflare D1 and Turso, where the bill follows the rows a query reads. Several patterns, such as an index column gap or a function wrapped around an indexed column, hurt in PostgreSQL too, but its planner differs, so treat the advice there as a lead and check it with EXPLAIN.

How do I know a suggested fix really helps?

Each report ends with a way to check: run EXPLAIN QUERY PLAN against a local SQLite copy of the schema and look for SEARCH instead of SCAN, and on D1 compare meta.rows_read before and after. We confirmed every planted problem and every accepted fix in our tests the same way.

Will it invent problems in healthy SQL?

Claude Sonnet answered 'No findings.' for our clean schema. Claude Haiku invented a finding there and suggested a DELETE with LIMIT that standard SQLite rejects, so with Haiku, run each suggested statement before relying on it.

What is the D1 parameter finding about?

D1 rejects a statement with more than 100 bound parameters. An id list built from your data, or a multi-row insert, uses one parameter per value, so code that worked at launch fails on its own when a reader saves the 101st item. The skill points to such places and suggests chunks of 50.

Read more

Share

Read this page as Markdown: /skills/sql-query-optimizer.md.

network baseprotocol x402asset USDCselling: trueskills 13