Developer Tools

SQL Index Generator

Paste a slow query and get the indexes it needs. The generator reads the WHERE, JOIN, ORDER BY and GROUP BY clauses, orders the columns of each composite index the way databases use them, equality first and then one range or sort column, skips indexes that already exist in your schema, and explains patterns that no index can help, such as functions on columns or LIKE patterns starting with %.

  • Runs in your browser
  • No sign-up
  • Free to use
Start from an example

With the schema, indexes that already exist are recognised and primary keys are not indexed twice.

Options

    How to use SQL Index Generator

    1. Paste the slow query.
    2. Paste the schema with existing indexes (optional).
    3. Choose the database and options.
    4. Create the suggested indexes and compare the query plan.

    SQL Index Generator features

    Column order

    Equality columns, then a range or ORDER BY column.

    Joins

    Indexes on the columns used to join tables.

    Existing indexes

    Recognised from the schema, including prefixes.

    Covering indexes

    INCLUDE columns in PostgreSQL and SQL Server.

    Online builds

    CONCURRENTLY, ONLINE = ON or LOCK = NONE.

    Anti-patterns

    Functions on columns, leading wildcards and OR across columns.

    When to use SQL Index Generator

    • Fixing a query that shows up in the slow query log.
    • Reviewing indexes before an application goes live.
    • Learning how composite indexes work.
    • Explaining to a team why a query cannot use an index.

    SQL Index Generator FAQ

    Why does column order matter?

    A B-tree index is sorted by its first column, then the second, and so on. Equality conditions narrow it to one contiguous range, which a following range or sort column can use; after a range condition, later columns cannot be used for searching.

    Why is YEAR(created_at) = 2025 slow?

    Wrapping a column in a function hides it from the index. Use created_at >= '2025-01-01' AND created_at < '2026-01-01', or an expression index.

    Why does LIKE '%text' not use the index?

    An index is sorted from the first character; a pattern starting with a wildcard has no starting point. Full-text search or trigram indexes help instead.

    What is a covering index?

    An index that contains every column the query reads, so the table itself does not need to be visited. PostgreSQL and SQL Server add such columns with INCLUDE.

    Should I create every suggestion?

    Each index slows down writes and uses space. Create the ones that serve frequent or important queries and confirm the improvement with EXPLAIN.

    Is the query executed?

    No. It is analysed in your browser.

    Indexes that queries can use

    Most slow queries are slow because the database has to read far more rows than it returns. An index lets it jump to the matching rows, but only if the index columns match how the query filters and sorts. Choosing those columns and their order is the core of query tuning.

    The generator reads the query’s structure. Conditions such as column = value, IN lists and IS NULL are equality conditions; comparisons, BETWEEN and prefix LIKE patterns are range conditions; ORDER BY and GROUP BY columns describe the requested order; and ON clauses and column = other.column conditions are joins. Aliases are resolved to their tables.

    For each table, the suggested index lists the equality columns first and then one range column, or the ORDER BY columns when there is no range condition, because an index can serve a range or a sort after the equality columns but not columns after a range. Join columns get their own index unless they are the table’s primary key.

    With your schema pasted, existing indexes are taken into account: when an index already starts with the suggested columns, the suggestion is replaced by a note naming it. In MySQL, the automatic indexes behind foreign keys count as existing indexes.

    Some query shapes defeat every index: functions applied to columns, LIKE patterns that begin with %, and OR conditions across different columns. These are explained with the alternative that works, such as rewriting a YEAR() condition as a date range or splitting an OR into a UNION ALL.

    Other useful tools