GimmeJob
Sign in
Databases, SQL & BI · SQL · Chapter 12 / 17

SQL learning path

Indexes, EXPLAIN & query performance

An index is an additional data structure that helps the engine locate rows without scanning every row. Indexes can transform query performance, but every index consumes storage and adds work to INSERT/UPDATE/DELETE operations.

What an index helps

Indexes are often useful for selective WHERE predicates, join keys, and ORDER BY patterns. A primary key normally creates or uses an index automatically, depending on the engine.

A query such as WHERE customer_id = ? over millions of orders is a typical candidate for an index on orders(customer_id).

Single-column indexes

SQL
SQLite · sample DB · browser sandbox
Result
Run the query to see the result.

This is static because schema modification is not enabled in learning blocks. In a real database, benchmark the actual workload instead of adding indexes mechanically.

Composite indexes and column order

SQL
SQLite · sample DB · browser sandbox
Result
Run the query to see the result.

Column order matters. An index beginning with customer_id can efficiently support many searches constrained by customer_id, but it is not equivalent to a separate index beginning with status.

Covering indexes

If an index contains all columns required by a query, some engines can answer it without reading the base table for each match. This can be fast, but wider indexes consume more space and maintenance work.

Selectivity and low-cardinality columns

An index on a boolean-like or low-cardinality status column may be unhelpful when a large fraction of the table matches. Data distribution matters as much as syntax.

EXPLAIN instead of intuition

PostgreSQL and SQLite provide EXPLAIN facilities that show the chosen plan. PostgreSQL also supports EXPLAIN ANALYZE, which actually executes the query and reports observed timing/row information. Use production-like data and caution with write queries.

Learn to inspect:

  • scan type (sequential/table scan versus index access),
  • estimated versus actual rows,
  • join strategy and join order,
  • sort/aggregate steps,
  • repeated loops,
  • large intermediate result sets.

Performance anti-patterns

Common issues include selecting unnecessary columns, missing join predicates, functions/casts that prevent useful index access, deep OFFSET pagination, N+1 application queries, leading-wildcard searches, and aggregating far more rows than needed.

Practice: explain which index you would consider for “all paid orders for one customer ordered by order_date descending,” and why column order matters.

Source registry

3 chapter references · Under review
SQLite Query Planning

Accessible explanation of indexes, lookup strategies, multi-column indexes, covering indexes, and query planning trade-offs.

SQLite · official documentation
Source ↗
PostgreSQL 18 — Queries

Detailed reference for FROM/WHERE/GROUP BY/HAVING, set operations, sorting, LIMIT/OFFSET, CTEs, recursive queries, and query processing.

PostgreSQL Global Development Group · official documentation
Source ↗
PostgreSQL 18 — Data Definition

Reference for tables, defaults, generated columns, constraints, privileges, schemas, inheritance/partitioning concepts, and other DDL topics.

PostgreSQL Global Development Group · official documentation
Source ↗