Cloud FinOps & Infrastructure ScalingPlaybook3 min readUpdated September 2026

Reading a Query Plan Well Enough to Know Which Index You Actually Need

To find the index a slow query actually needs, read its EXPLAIN ANALYZE plan before adding anything, because an index added blindly often does not help and adds write overhead to every future insert and update on that table. Reading the real plan turns index tuning from guesswork into a targeted fix.

Here's how to read one well enough to know the difference.

Run EXPLAIN ANALYZE, Not Just EXPLAIN

EXPLAIN shows you the planner's estimated plan; EXPLAIN ANALYZE actually runs the query and shows you what really happened, including real row counts and real timing per step. The gap between the planner's estimate and reality is itself diagnostic: a large gap often means your table statistics are stale, which can cause the planner to pick a bad plan even when a good index already exists. Always read the analyzed version before deciding a query needs a new index at all.

How do you find the sequential scan that is the real problem?

A sequential scan, reading every row in a table, isn't automatically bad; on a small table it's often faster than the overhead of using an index at all. The sequential scan worth fixing is the one on a large table, filtering down to a small fraction of rows, taking a meaningful share of the query's total time. Look at the actual row counts in the plan: a sequential scan reading a million rows to return twenty is a strong signal an index on the filtered column would help. A sequential scan reading a million rows to return eight hundred thousand often isn't, since an index wouldn't meaningfully narrow that down anyway.

How do you match an index to the query, not the table?

An index on a single column helps a query that filters on exactly that column, but many real queries filter on a combination of columns, or filter on one column while sorting by another. A composite index, covering the columns in the order your query actually uses them, often outperforms two separate single-column indexes for a query that needs both. Get the column order in a composite index wrong, and the index may not get used at all for a filter that doesn't lead with its first column.

The Cost Side Nobody Checks Before Adding One

Every index speeds up the specific reads it's built for and slows down every write to that table, since the database has to update the index alongside the row itself. A table with heavy write traffic and a dozen indexes, several unused, pays that cost on every insert and update without getting anything back for the unused ones. Periodically check which indexes are actually being used by your query planner, most databases expose this, and drop the ones that aren't earning their write overhead.

A Worked Example

Say a report page that filters orders by customer and sorts by date takes four seconds to load. EXPLAIN ANALYZE shows a sequential scan reading two million order rows to return the forty that belong to one customer, with almost the entire four seconds spent in that scan. A composite index on customer ID and order date, in that order, turns that same query into an index scan reading roughly forty rows directly, and the report page drops to double-digit milliseconds. The fix wasn't guessed, it came directly from reading which step in the plan actually consumed the time.

Letting an Advisory Tool Suggest Indexes, Then Checking Its Work

Several databases and third-party tools can suggest indexes automatically based on observed query patterns, and these suggestions are a reasonable starting point, especially on a schema too large to review by hand. Treat the suggestion as a hypothesis, not a final answer: apply it in a staging environment, run EXPLAIN ANALYZE on the actual queries it's meant to help, and confirm the planner is choosing to use it before rolling it out to production. An automated suggestion applied blindly carries the same write-overhead risk as a manually guessed index, since the tool doesn't know your actual write volume or how many other indexes are already competing for the same benefit.

A short checklist before you add any index:

  • Run EXPLAIN ANALYZE rather than plain EXPLAIN, and compare the planner's estimates against the real row counts and timing.
  • Fix only sequential scans on large tables that filter down to a small fraction of rows and take a meaningful share of query time.
  • Build composite indexes with columns in the order the query actually filters and sorts, instead of stacking single-column indexes.
  • Periodically drop indexes that are never used, since each one slows every write to the table.
  • Test any advisory tool suggestion in staging with EXPLAIN ANALYZE before applying it to production.
Executive Capability Standard

What Good Looks Like

Good indexing means every index in use is traceable to a real query plan that shows it being used, and slow queries get diagnosed from EXPLAIN ANALYZE output before any index gets added.

Building The Capability (5-Stage Skill Ladder)

1. Learn:Run EXPLAIN ANALYZE on your five slowest recurring queries to see which ones are actually spending time in a sequential scan worth fixing.
2. Do Manually:Manually add and test a targeted composite index for the highest-impact query you found, confirming with EXPLAIN ANALYZE that it's actually being used.
3. Delegate:Have a backend or database-focused engineer own a recurring review of slow query logs and index usage stats.
4. Automate:Add automated slow-query logging and index-usage reporting so candidates for new or removable indexes surface without manual digging.
5. Buy:Bring in a database performance specialist if query plans are consistently confusing or if you're dealing with a large, complex schema where indexing tradeoffs interact across many tables.

How to Get Started

Frequently Asked Questions

Why would a query still use a sequential scan even after we added an index?

Usually because of stale table statistics, a filter that does not match the index's leading column, or a table small enough that a sequential scan is faster. Stale statistics make the planner underestimate how selective the index would be. Run EXPLAIN ANALYZE after adding the index to confirm it is actually being used.

How many indexes are too many on one table?

There's no fixed number; it depends on your write volume and how many of the indexes are actually used. A read-heavy table with low write volume can support more indexes without a noticeable cost. A high-write table should carry only the indexes that measurably support real queries, checked periodically rather than assumed to still be needed.

Should we just add an index to every column that shows up in a WHERE clause?

No. That approach adds write overhead across the board while missing the composite indexes that would actually help queries filtering on more than one column together. Base index decisions on actual query plans for your slowest, most frequent queries, not a blanket rule applied to every column mentioned in a filter.

About the numbers

This guide doesn't quote a sourced benchmark. Figures in it are estimates or general guidance, so check them against your own numbers.

Related Guides