Question: Monitoring
Why doesn't pg_stat_statements show all my queries?
Answered in the first paragraph. Last updated .
Four reasons, and the common one is eviction. The set of tracked statements is a fixed size fixed at startup, and when more distinct statements appear than it holds, the least executed ones are discarded to make room. The other three: statements issued inside functions are not counted by default, utility commands can be excluded, and a statement that has not finished yet has not been recorded at all.
Telling eviction from the rest
The extension keeps its own health row, and it counts how many times entries have been thrown away. A number that climbs steadily means the table is too small for the workload, and that counter is the only honest way to know, because the symptom otherwise is simply that things you remember seeing are no longer there.
Before raising the size, find out why the distinct count is so high. Statements built by string concatenation, with the values written into the text, produce a separate entry for every value, so one query shape can occupy the entire table on its own. Parameterising it collapses thousands of entries into one and is a better fix than more memory, which is the practical payoff of understanding how a statement is fingerprinted.
If the size does need raising, it needs a restart and more shared memory, so it is a planned change rather than an incident response.
The other three, and one reading trap
Nested statements are off by default, which means a workload that runs everything through stored procedures shows the procedure calls and nothing underneath. Turning them on has a real cost and changes what a total means, because the outer and inner statements are both counted and summing the column double-counts the work: top-level versus nested statements covers reading it correctly.
Utility commands have their own switch, which is why a cluster spending its afternoons on index builds can look idle here.
And nothing appears until it completes. A statement that has been running for two hours is invisible in this view and perfectly visible in the session view, which is the division of labour between the two and the reason reading the session view correctly matters.
One last subtlety. After a reset, an entry with small numbers might be a rare statement or a recently recreated one, and before PostgreSQL 17 there was no way to tell. Now each row carries its own start timestamp. For what any of this costs to collect, see is pg_stat_statements safe to enable in production, and for the sampling approach that fills the gaps, active session history.