pg_stat_statements is a contributed extension for PostgreSQL that logs all queries and how long they took. If you aggregate on this, you can determine where your PostgreSQL spends the most time and what to optimize.

How it works and how you install it is for another blog post.

Total time


SELECT
  (total_time / 1000 / 60) AS total,
    (total_time/calls) AS avg, calls,
      SUBSTRING(query FROM 0 FOR 250)
      FROM pg_stat_statements
      WHERE calls > 100
      ORDER BY 1 DESC
      LIMIT 25;

This one is important because you could have some terribly slow query that uses lots of sequential scans, but perhaps it's only used once a week, so who cares?

Most common


SELECT calls, substring(query from 0 for 250)
FROM pg_stat_statements
ORDER BY calls DESC LIMIT 20;

The total time (above) matters more than just the number of times it's used. However, this can be very helpful to spot things like "N+1 problems" such as this use of an ORM:


for user in User.objects.all():
    for profile in UserProfile.objects.filter(user=user):
        print(profile.theme_preference)

This is likely to be numerous queries when it could be 1. They might all be pretty fast so their total time might not show in the total-time query above.

Reset


select pg_stat_statements_reset();

I run this manually when I know I've shipped a change that will stop doing certain queries that could be dominating stats. If they're not going to happen any more, it's no use worrying about them.

Caveat about the times

My particular PostgreSQL is old. That means that total_time in pg_stat_statements is the time spent in the execution phase and thus excludes the parse, rewrite and plan phases. In more modern versions of PostgreSQL you use total_plan_time and/or total_exec_time whose names make this clearer.

Comments

Your email will never ever be published.

Related posts