What a sequential scan means
A sequential scan reads table pages and evaluates rows without using an index to locate the starting rows. PostgreSQL's planner compares estimated plan costs and can correctly choose a sequential scan when a query needs much of a table, the table is small, or indexed access would cost more.
Sequential scans also support normal tasks such as analytics, exports, maintenance-related reads, and queries without a useful index. The presence of a Seq Scan node is therefore evidence about one plan—not proof of a missing index.
Inspect cumulative table scan counters
This read-only query ranks user tables by rows fetched through sequential scans and includes the database statistics reset timestamp. The counters describe activity accumulated in the available statistics window.
SELECT
s.schemaname,
s.relname AS table_name,
s.seq_scan,
s.seq_tup_read,
s.idx_scan,
s.idx_tup_fetch,
s.n_live_tup AS estimated_live_rows,
CASE
WHEN s.seq_scan > 0
THEN round(s.seq_tup_read::numeric / s.seq_scan, 1)
END AS average_rows_per_sequential_scan,
d.stats_reset
FROM pg_stat_user_tables AS s
CROSS JOIN (
SELECT stats_reset
FROM pg_stat_database
WHERE datname = current_database()
) AS d
ORDER BY s.seq_tup_read DESC
LIMIT 50;Interpret the counters
| Counter | What it reports | What it cannot prove |
|---|---|---|
seq_scan | Number of sequential scans initiated on the table. | The number of SQL statements or whether those scans were inefficient. |
seq_tup_read | Live rows fetched by sequential scans. | Physical disk reads; rows may be served from shared buffers. |
idx_scan | Index scans initiated on the table. | That index access is always preferable or exactly one search occurred per query. |
idx_tup_fetch | Live table rows fetched by index scans. | All index entries examined or the benefit of a particular index. |
n_live_tup | Estimated live rows in the table. | An exact row count. |
stats_reset | When database-wide cumulative statistics were last reset. | The exact lifetime of counters that may have been reset separately. |
Inspect a suspected query plan safely
Use plain EXPLAIN first. It shows the planner's estimated plan without executing the statement. Replace the sample table and predicate only with a query you are authorized to inspect.
EXPLAIN (COSTS, VERBOSE)
SELECT *
FROM public.orders
WHERE customer_id = 42;When a sequential scan deserves review
- A large relation repeatedly reads many rows to return a small, selective result.
- A high-contribution query fingerprint aligns with the same table and time window.
- Planner row estimates differ substantially from observed rows in a deliberately reviewed execution plan.
- An expected supporting index is absent, invalid, unusable for the predicate, or poorly aligned with column order and operators.
- Statistics or planner assumptions may be stale after substantial table changes.
Even then, an index is only one possible response. Query shape, partition pruning, statistics quality, result selectivity, storage behavior, and write overhead all belong in the review.
Common misleading interpretations
- A high
seq_scancount does not mean every scan was slow or read the entire table from disk. - More sequential scans than index scans is not a universal problem threshold.
- Disabling sequential scans is a diagnostic influence on planner choices, not a general production fix.
- Creating an index can increase storage and write cost without improving a broad-read query.
- A cumulative table counter cannot identify the exact statement responsible; correlate it with workload evidence and plans.
When DatabaseMeter can help
The PostgreSQL health check captures bounded relation size, estimated rows, sequential scans, rows fetched sequentially, and index scans. It labels disproportionate sequential-scan activity as an observation and explicitly notes that small tables and analytical workloads can make it appropriate.
Connected telemetry can compare supported relation counters over time. The pg_stat_statements analyzer can separately rank normalized query fingerprints without SQL text, helping narrow the workload window before an authorized plan review.
Definitions and sources
Provider and PostgreSQL statements last reviewed August 29, 2026. Pricing consoles and invoices remain authoritative.
Related database resources
How to interpret pg_stat_statements
Rank normalized query fingerprints while accounting for cumulative counters, resets, and privacy.
Open resourcePostgreSQL index size guide
Measure table and index footprint without reading application rows.
Open resourcePostgreSQL health check
Analyze bounded PostgreSQL catalog statistics locally—without connecting your database.
Open resource