Skip to content
PHP2Shell: The PHP Bug
Akshay Thakare

Indexes and Query Plans: Why a Query Is Slow

Read an EXPLAIN plan, understand when an index helps, and the common reasons a database ignores the index you created.

SQLIntermediate2 min readUpdated 11 Oct 2026

Start with the plan

SQL.sql
EXPLAIN ANALYZE
SELECT * FROM transactions
WHERE store_id = 1001 AND ingested_at >= '2026-01-05';

Look for:

  • Seq Scan on a large table: every row is read.
  • Index Scan / Index Only Scan: the index narrows the rows.
  • Estimated vs actual rows far apart: statistics are stale (ANALYZE).
  • The node with the largest actual time: optimise that one first.

When a B-tree index helps

A B-tree index keeps keys sorted, so the database can jump to a range instead of scanning.

SQL.sql
CREATE INDEX ON transactions (store_id, ingested_at);

Column order matters. This index serves store_id = ? and store_id = ? AND ingested_at >= ?, but not ingested_at >= ? alone.

Why your index is ignored

CauseExampleFix
Function on the columnWHERE date(ingested_at) = ...Use a range, or an expression index
Low selectivityWHERE status = 'paid' matches 90%A scan is genuinely cheaper
Type mismatchComparing text to an integer columnMatch the types
Leading wildcardLIKE '%abc'Full-text or trigram index

Indexes are not free

Every insert and update must also update each index. Tables that receive heavy writes should only carry the indexes that real queries use.

Finished this note?

Share