Skip to content

Features

This document describes the pg_stat_monitor features and gives the usage examples. For how to install and set up pg_stat_monitor, see the Installation instructions.

Note

Column names differ depending on the PostgreSQL version you are using. The following usage examples are provided for PostgreSQL version 15. For earlier versions of PostgreSQL, please consult the pg_stat_monitor reference.

Time buckets

Instead of supplying one set of ever-increasing counts, pg_stat_monitor computes stats for a configured number of time intervals; time buckets. This allows for much better data accuracy, especially in the case of high-resolution or unreliable networks.

Example

SELECT bucket, bucket_start_time, query,calls FROM pg_stat_monitor ORDER BY bucket;

Output:

-[ RECORD 1 ]-----+-----------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------
bucket            | 1
bucket_start_time | 2023-02-21 08:20:00+00
query             | INSERT INTO players (id, about, age) VALUES (generate_series($1, $2),  repeat($3, $4) || $5 || trunc(random()*$6), trunc(random()*
$7 * $8 + $9))
calls             | 1

The bucket parameter shows the number of a bucket for which a given record belongs.

The bucket_start_time shows the start time of the bucket. query shows the actual query text. calls shows how many times a given query was called.

Table and index access statistics per statement

pg_stat_monitor collects the information about what tables were accessed by a statement. This allows you to identify all queries which access a given table easily.

Query and client information

pg_stat_monitor provides additional metrics for detailed analysis of query performance from various perspectives, including client connection details like user name, application name, IP address to name a few relevant columns. With this information, pg_stat_monitor enables users to track a query to the originating application. More details about the application or query may be incorporated in the SQL query in a Google’s Sqlcommenter format.

Examples

1. Query information

The following example shows the usename, database name, unique queryid hash, query, and the total number of calls of that query.

SELECT userid,  datname, queryid, substr(query,0, 50) AS query, calls FROM pg_stat_monitor;

Output:

 userid  | datname  |     queryid      |                       query                       | calls
---------+----------+------------------+---------------------------------------------------+-------
 10 | postgres | 939C2F56E1F6A174 | END                                               |   561
 10 | postgres | 2A4437C4905E0E23 | SELECT abalance FROM pgbench_accounts WHERE aid = |   561
 10 | postgres | 4EE9ED0CDF143477 | SELECT userid,  datname, queryid, substr(query,$1 |     1
 10 | postgres | 8867FEEB8A5388AC | vacuum pgbench_branches                           |     1
 10 | postgres | 41D1168FB0733CAB | select count(*) from pgbench_branches             |     1
 10 | postgres | E5A889A8FF37C2B1 | UPDATE pgbench_accounts SET abalance = abalance + |   561
 10 | postgres | 4876BBA9A8FCFCF9 | truncate pgbench_history                          |     1
 10 | postgres | 22B76AE84689E4DC | INSERT INTO pgbench_history (tid, bid, aid, delta |   561
 10 | postgres | F6DA9838660825CA | vacuum pgbench_tellers                            |     1
 10 | postgres | 214646CE6F9B1A85 | BEGIN                                             |   561
 10 | postgres | 27462943E814C5B5 | UPDATE pgbench_tellers SET tbalance = tbalance +  |   561
 10 | postgres | 4F66D46F3D4151E  | SELECT userid,  dbid, queryid, substr(query,0, 50 |     1
 10 | postgres | 6A02C123488B95DB | UPDATE pgbench_branches SET bbalance = bbalance + |   561
(13 rows)

2. Application details

SELECT application_name, client_ip, substr(query,0,100) as query FROM pg_stat_monitor;

Output:

 application_name | client_ip |                                                query
------------------+-----------+-----------------------------------------------------------------------------------------------------
 psql             | 127.0.0.1 | [200~INSERT INTO DOCUMENT_TEMPLATE(id,name, short_description, author,                             +
                  |           |
 psql             | 127.0.0.1 | SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, c.relhastriggers, c.relrowsecurity, c.
 psql             | 127.0.0.1 | SELECT a.attname,                                                                                  +
                  |           |   pg_catalog.format_type(a.atttypid, a.atttypmod),                                                 +
                  |           |   (SELECT pg_catalog.pg_get_ex
 psql             | 127.0.0.1 | INSERT INTO document_template (stringColumn) VALUES (repeat("Wow ", 3));
 psql             | 127.0.0.1 | create table DOCUMENT_TEMPLATE;
 psql             | 127.0.0.1 | INSERT INTO players (id, about, age) VALUES (generate_series($1, $2),  repeat($3, $4) || $5 || trun
 psql             | 127.0.0.1 | SELECT d.datname as "Name",                                                                        +
                  |           |        pg_catalog.pg_get_userbyid(d.datdba) as "Owner",                                            +
                  |           |        pg_catal
 psql             | 127.0.0.1 | Select * from DOCUMENT_TEMPLATE;
 psql             | 127.0.0.1 | ~                                                                                                  +
                  |           | INSERT INTO DOCUMENT_TEMPLATE(id,name, short_description, author,                                  +
                  |           |                               d
 psql             | 127.0.0.1 | INSERT INTO DOCUMENT_TEMPLATE(id,name, short_description, author,                                  +
                  |           |                               des
 psql             | 127.0.0.1 | SELECT c.oid,                                                                                      +
                  |           |   n.nspname,                                                                                       +
                  |           |   c.relname                                                                                        +
                  |           | FROM pg_catalog.pg_class c                                                                         +
                  |           |      LEFT JOIN pg_catalog.pg_name
 psql             | 127.0.0.1 | INSERT INTO DOCUMENT_TEMPLATE(id,name, short_description, author,                                  +
                  |           |                               des
 psql             | 127.0.0.1 | SELECT bucket, bucket_start_time, query,calls FROM pg_stat_monitor ORDER BY bucket
 psql             | 127.0.0.1 | INSERT INTO test (stringColumn) VALUES (repeat("Wow ", 3));
(13 rows)

Query timing information

Understanding query execution time stats helps you identify what affects query performance and take measures to optimize it. pg_stat_monitor collects the total, min, max and average (mean) time it took to execute a particular query and provides this data in separate columns.

Example

SELECT  userid,  total_exec_time, min_exec_time, max_exec_time, mean_exec_time, query FROM pg_stat_monitor;

Output:

userid | total_exec_time | min_exec_time | max_exec_time | mean_exec_time |                                            query
--------+-----------------+---------------+---------------+----------------+----------------------------------------------------------------------------------------------
     10 |        1.532168 |      0.749108 |       0.78306 |       0.766084 | SELECT userid,  datname, queryid, substr(query,$1, $2) AS query, calls FROM pg_stat_monitor
     10 |        0.755857 |      0.755857 |      0.755857 |       0.755857 | SELECT application_name, client_ip, substr(query,$1,$2) as query FROM pg_stat_monitor
     10 |               0 |             0 |             0 |              0 | SELECT  userid,  total_time, min_time, max_time, mean_time, query FROM pg_stat_monitor;
     10 |               0 |             0 |             0 |              0 | SELECT  userid,  total_exec_time, min_time, max_time, mean_time, query FROM pg_stat_monitor;
(4 rows)

Query execution plan information

Every query has a plan that was constructed for its execution. Collecting the query plan information as well as monitoring query plan timing helps you understand how you can modify the query to optimize its execution. It also helps to make communication about the query clearer when discussing query performance with other DBAs and application developers.

Example

SELECT substr(query,0,50), query_plan from pg_stat_monitor limit 10;

Output:

                      substr                       |                                                  query_plan
---------------------------------------------------+---------------------------------------------------------------------------------------------------------------
 select o.n, p.partstrat, pg_catalog.count(i.inhpa | Limit                                                                                                        +
                                                   |   ->  GroupAggregate                                                                                         +
                                                   |         Group Key: (array_position(current_schemas(true), n.nspname)), p.partstrat                           +
                                                   |         ->  Sort                                                                                             +
                                                   |               Sort Key: (array_position(current_schemas(true), n.nspname)), p.partstrat                      +
                                                   |               ->  Nested Loop Left Join                                                                      +
                                                   |                     ->  Nested Loop Left Join                                                                +
                                                   |                           ->  Nested Loop                                                                    +
                                                   |                                 Join Filter: (c.relnamespace = n.oid)                                        +
                                                   |                                 ->  Index Scan using pg_class_relname_nsp_index on pg_class c                +
                                                   |                                       Index Cond: (relname = 'pgbench_accounts'::name)                       +
                                                   |                                 ->  Seq Scan on pg_namespace n                                               +
                                                   |                                       Filter: (array_position(current_schemas(true), nspname) IS NOT NULL)   +
                                                   |                           ->  Index Scan using pg_partitioned_table_partrelid_index on pg_partitioned_table p+
                                                   |                                 Index Cond: (partrelid = c.oid)                                              +
                                                   |                     ->  Bitmap Heap Scan on pg_inherits i                                                    +
                                                   |                           R
 SELECT abalance FROM pgbench_accounts WHERE aid = | Index Scan using pgbench_accounts_pkey on pgbench_accounts                                                   +
                                                   |   Index Cond: (aid = 102232)
 BEGIN;                                            |
 END;                                              |
 SELECT substr(query,$1,$2), query_plan from pg_st |
 SELECT substr(query,$1,$2),calls, planid,query_pl | Limit                                                                                                        +
                                                   |   ->  Subquery Scan on pg_stat_monitor                                                                       +
                                                   |         ->  Result                                                                                           +
                                                   |               ->  Sort                                                                                       +
                                                   |                     Sort Key: p.bucket_start_time                                                            +
                                                   |                     ->  Hash Join                                                                            +
                                                   |                           Hash Cond: (p.dbid = d.oid)                                                        +
                                                   |                           ->  Function Scan on pg_stat_monitor_internal p                                    +
                                                   |                           ->  Hash                                                                           +
                                                   |                                 ->  Seq Scan on pg_database d                                                +
                                                   |               SubPlan 1                                                                                      +
                                                   |                 ->  Function Scan on pg_stat_monitor_internal s                                              +
                                                   |                       Filter: (queryid = p.top_queryid)
 select count(*) from pgbench_branches             | Aggregate                                                                                                    +
                                                   |   ->  Seq Scan on pgbench_branches
 UPDATE pgbench_tellers SET tbalance = tbalance +  |
 vacuum pgbench_tellers                            |
 UPDATE pgbench_accounts SET abalance = abalance + |
(10 rows)

The plan column does not contain costing, width and other values. This is an expected behavior as each row is an accumulation of statistics based on plan and among other key columns. Plan is only available when the pgsm_enable_query_plan configuration parameter is enabled.

Use of actual data or parameters placeholders in queries

You can select whether to see queries with parameters placeholders or actual query data. The benefit of having the full query example is in being able to run the EXPLAIN command on it to see how its execution was planned. As a result, you can modify the query to make it run better.

Query type filtering

pg_stat_monitor monitors queries per type (SELECT, INSERT, UPDATE or DELETE). It classifies the queries in the cmd_type and cmd_type_text columns. This way you can separate the queries you are interested in and focus on identifying the issues and optimizing query performance.

Example

SELECT bucket, substr(query,0, 50) AS query, cmd_type, cmd_type_text FROM pg_stat_monitor WHERE elevel = 0;

Output:

 bucket |                       query                       | cmd_type | cmd_type_text
--------+---------------------------------------------------+----------+---------------
      1 | SELECT $2 FROM ONLY "public"."users" x WHERE "id" |        1 | SELECT
      1 | INSERT INTO players (id, about, age) VALUES (gene |        3 | INSERT
      1 | SELECT datname FROM pg_catalog.pg_database  WHERE |        1 | SELECT
      1 | INSERT INTO users(email)                         +|        3 | INSERT
        | SELECT                                           +|          |
        |   $1 || seq || $2                                 |          |
      1 | SELECT * FROM posts LIMIT $1                      |        1 | SELECT
      1 | SELECT * FROM comments LIMIT $1                   |        1 | SELECT
      1 | INSERT INTO posts(user_id, title)                +|        3 | INSERT
        | WITH expanded A                                   |          |
      1 | INSERT INTO comments(user_id, post_id, body)     +|        3 | INSERT
        | WITH                                              |          |
      1 | SELECT bucket, substr(query,$1, $2) AS query, cmd |        1 | SELECT
      1 | SELECT bucket, substr(query,$1, $2) AS query, cmd |        1 | SELECT
      1 | SELECT substr(query,$1,$2), query_plan from pg_st |        1 | SELECT
      1 | SELECT $2 FROM ONLY "public"."posts" x WHERE "id" |        1 | SELECT
      1 | SELECT * FROM users                               |        1 | SELECT
      2 | Update users SET email= $1 where id=$2            |        2 | UPDATE
(15 rows)

Query metadata

Google’s Sqlcommenter is a useful tool that in a way bridges that gap between ORM libraries and understanding the database performance. And pg_stat_monitor supports it.

You can put any key-value data like what client executed a query or if it is a testing vs a production query in the comments using the /* … */ syntax in your SQL statements. pg_stat_monitor parses this information and outputs it in the comments column in the pg_stat_monitor view.

Please note that only the latest comment value is preserved per row. The comments may be put in any format that can be parsed by a tool.

For more information about the comments’ syntax, refer to the Sqlcommenter documentation.

Example

To store key-value pairs in a single value, the hstore data type is used. To start working with hstore, enable the hstore extension

CREATE EXTENSION hstore;

Create a function to convert data from text form to hstore.

CREATE FUNCTION text_to_hstore(s text) RETURNS hstore AS $$
BEGIN
    RETURN hstore(s::text[]);
EXCEPTION WHEN OTHERS THEN
    RETURN NULL;
END; $$ LANGUAGE plpgsql STRICT;

Add comments.

SELECT 1 AS num /* { "application", java_app, "real_ip", 192.168.1.1} */;

Output:

 num
-----
   1
(1 row)
SELECT 1 AS num1,2 AS num2 /* { "application", java_app, "real_ip", 192.168.1.2} */;

Output:

 num1 | num2
------+------
    1 |    2
(1 row)
SELECT 1 AS num1,2 AS num2, 3 AS num3 /* { "application", java_app, "real_ip", 192.168.1.3} */;

Output:

 num1 | num2 | num3
------+------+------
    1 |    2 |    3
(1 row)
SELECT 1 AS num1,2 AS num2, 3 AS num3, 4 AS num4 /* { "application", psql_app, "real_ip", 192.168.1.3} */;

Output:

 num1 | num2 | num3 | num4
------+------+------+------
    1 |    2 |    3 |    4
(1 row)

View query metadata

SELECT query, text_to_hstore(comments) as comments_tags FROM pg_stat_monitor;

Output:

                                                     query                                                     |                    comments_tags
---------------------------------------------------------------------------------------------------------------+-----------------------------------------------------
 SELECT $1 AS num /* { "application", psql_app, "real_ip", 192.168.1.3) */                                     | "real_ip"=>"192.168.1.1", "application"=>"java_app"
 SELECT pg_stat_monitor_reset();                                                                               |
 SELECT query, comments, text_to_hstore(comments) FROM pg_stat_monitor;                                        |
 SELECT $1 AS num1,$2 AS num2, $3 AS num3 /* { "application", java_app, "real_ip", 192.168.1.3} */             | "real_ip"=>"192.168.1.3", "application"=>"java_app"
 select query, text_to_hstore(comments) as comments_tags from pg_stat_monitor;                                 |
 SELECT $1 AS num1,$2 AS num2 /* { "application", java_app, "real_ip", 192.168.1.2} */                         | "real_ip"=>"192.168.1.2", "application"=>"java_app"
 SELECT $1 AS num1,$2 AS num2, $3 AS num3, $4 AS num4 /* { "application", psql_app, "real_ip", 192.168.1.3} */ | "real_ip"=>"192.168.1.3", "application"=>"psql_app"
(7 rows)
select query, text_to_hstore(comments)->'application' as application_name from pg_stat_monitor;

Output:

                                                     query                                                     | application_name
---------------------------------------------------------------------------------------------------------------+----------
 SELECT $1 AS num /* { "application", psql_app, "real_ip", 192.168.1.3) */                                     | java_app
 SELECT pg_stat_monitor_reset();                                                                               |
 select query, text_to_hstore(comments)->"real_ip" as comments_tags from pg_stat_monitor;                      |
 select query, text_to_hstore(comments)->$1 from pg_stat_monitor                                               |
 select query, text_to_hstore(comments) as comments_tags from pg_stat_monitor;                                 |
 select query, text_to_hstore(comments)->"application" as comments_tags from pg_stat_monitor;                  |
 SELECT $1 AS num1,$2 AS num2 /* { "application", java_app, "real_ip", 192.168.1.2} */                         | java_app
 SELECT $1 AS num1,$2 AS num2, $3 AS num3 /* { "application", java_app, "real_ip", 192.168.1.3} */             | java_app
 select query, comments, text_to_hstore(comments) from pg_stat_monitor;                                        |
 SELECT $1 AS num1,$2 AS num2, $3 AS num3, $4 AS num4 /* { "application", psql_app, "real_ip", 192.168.1.3} */ | psql_app
(10 rows)
select query, text_to_hstore(comments)->'real_ip' as real_ip from pg_stat_monitor;

Output:

                                                     query                                                     |  real_ip
---------------------------------------------------------------------------------------------------------------+-------------
 SELECT $1 AS num /* { "application", psql_app, "real_ip", 192.168.1.3) */                                     | 192.168.1.1
 SELECT pg_stat_monitor_reset();                                                                               |
 select query, text_to_hstore(comments)->"real_ip" as comments_tags from pg_stat_monitor;                      |
 select query, text_to_hstore(comments)->$1 from pg_stat_monitor                                               |
 select query, text_to_hstore(comments) as comments_tags from pg_stat_monitor;                                 |
 select query, text_to_hstore(comments)->"application" as comments_tags from pg_stat_monitor;                  |
 SELECT $1 AS num1,$2 AS num2 /* { "application", java_app, "real_ip", 192.168.1.2} */                         | 192.168.1.2
 SELECT $1 AS num1,$2 AS num2, $3 AS num3 /* { "application", java_app, "real_ip", 192.168.1.3} */             | 192.168.1.3
 select query, comments, text_to_hstore(comments) from pg_stat_monitor;                                        |
 SELECT $1 AS num1,$2 AS num2, $3 AS num3, $4 AS num4 /* { "application", psql_app, "real_ip", 192.168.1.3} */ | 192.168.1.3
(10 rows)

Top query tracking

Using functions is common. While running, functions can execute queries internally. pg_stat_monitor not only keeps track of all executed queries within a function, but also marks that function as top query.

Top query indicates the main query. To illustrate, for the SELECT query that is invoked within a function, the top query is calling this function.

This enables you to backtrack to the originating function and thus simplifies the tracking and analysis.

pg_stat_monitor doesn’t track top query for Stored procedures and other non-utility statements. To see the statistics data about stored procedures, enable the pg_stat_monitor.pgsm_track_utility configuration parameter.

To track subqueries within a function, set the pg_stat_monitor.pgsm_track configuration parameter to all.

Example

In the following example we create a function add2 that adds one parameter value to another one and call this function to calculate 1+2.

CREATE OR REPLACE function add2(int, int) RETURNS int as
$$
BEGIN
   return (select $1 + $2);
END;
$$ language plpgsql;
SELECT add2(1,2);

Output:

 add2
-----
   3
(1 row)

The pg_stat_monitor view shows all executed queries and shows the very first query in a row - calling the add2 function.

SELECT queryid, top_queryid, query, top_query FROM pg_stat_monitor;

Output:

     queryid      |   top_queryid    |                       query.                           |     top_query
------------------+------------------+-------------------------------------------------------------------------+-------------------
 3408CA84B2353094 |                  | select add2($1,$2)                                     |
 762B99349F6C7F31 | 3408CA84B2353094 | SELECT (select $1 + $2)                                | select add2($1,$2)
(2 rows)

Relations

pg_stat_monitor provides the list of tables involved in the query in the relations column. This reduces time on identifying the tables and simplifies the analysis.

Example

1. List all the table names involved in the query.

SELECT relations,query FROM pg_stat_monitor;

Output:

                          relations                            |
     query
----------------------------------------------------------------+-------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
                                                                | SELECT add2($1,$2)
                                                                | select pg_stat_monitor_reset()
 {public.pg_stat_monitor*,pg_catalog.pg_database}               | SELECT queryid, top_queryid, query, top_query FROM pg_stat_monitor
                                                                | (select $1 + $2)
 {public.users}                                                 | select * from users
 {public.posts}                                                 | Select * from posts where user_id=$1
                                                                | Select & from posts where user_id=3;
 {pg_catalog.pg_database}                                       | SELECT datname FROM pg_catalog.pg_database  WHERE datname LIKE $1                                                                                                                       +
(4 rows)

Example 2: List all the views and the name of the table in the view. Here we have a view “test_view”

\d+ test_view
                          View "public.test_view"
 Column |  Type   | Collation | Nullable | Default | Storage | Description 
--------+---------+-----------+----------+---------+---------+-------------
 foo_a  | integer |           |          |         | plain   | 
 bar_a  | integer |           |          |         | plain   | 
View definition:
 SELECT f.a AS foo_a,
    b.a AS bar_a
   FROM foo f,
    bar b;

Now when we query the pg_stat_monitor, it will show the view name and also all the table names in the view. Note that the view name is followed by an asterisk (*).

SELECT relations, query FROM pg_stat_monitor;

Output:

      relations      |    query                                                 
---------------------+----------------------------------------------------
 {test_view*,foo,bar} | select * from test_view
 {foo,bar}           | select * from foo,bar
(2 rows)

Monitoring queries terminated with ERROR, WARNING and LOG error levels

Monitoring queries that terminated with ERROR, WARNING, LOG states can give useful information to debug an issue. Such messages have the error level (elevel), error code (sqlcode), and error message (message).

pg_stat_monitor collects all this information and aggregates it so that you can measure performance for successful and failed queries separately, as well as understand why a particular query failed to execute successfully.

Example

SELECT substr(query,0,50) AS query, decode_error_level(elevel) AS elevel,sqlcode, calls, substr(message,0,50) message
FROM pg_stat_monitor;

Output:

                       query                       | elevel | sqlcode | calls |                      message
---------------------------------------------------+--------+---------+-------+---------------------------------------------------
 select substr(query,$1,$2) as query, decode_error |        |       0 |     1 |
 select bucket,substr(query,$1,$2),decode_error_le |        |       0 |     3 |
                                                   | LOG    |       0 |     1 | database system is ready to accept connections
 select 1/0;                                       | ERROR  |     130 |     1 | division by zero
                                                   | LOG    |       0 |     1 | database system was shut down at 2020-11-11 11:37
 select $1/$2                                      |        |       0 |     1 |
(6 rows)
          11277.79 | SELECT * FROM foo

Histogram

Histogram (the resp_calls parameter) provides a visual representation of query performance data distributed across buckets. With the help of the histogram function, you can view a timing/calling data graph in response to an SQL query.

The histogram output is controlled by the following configuration parameters:

  • pgsm_histogram_min – the minimum execution time for a query, in ms (default 1)
  • pgsm_histogram_max – the maximum execution time for a query, in ms (default 10000)
  • pgsm_histogram_buckets – the maximum number of buckets to be shown in histogram (default 20)

Example

SELECT bucket, queryid, resp_calls, query FROM pg_stat_monitor;

Output:

bucket |       queryid        |                  resp_calls                   |             query
--------+----------------------+-----------------------------------------------+--------------------------------
      1 | -7911769593731908992 | {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} | SELECT pg_stat_monitor_reset()
      3 |  2920803561901199087 | {0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,2,1,0,0,0,0} | SELECT pg_sleep($1)
(2 rows)                                        |                  |       |
SELECT * FROM histogram(3, '2920803561901199087') AS a(range TEXT, freq INT, bar TEXT);

Output:

           range           | freq |                                            bar
---------------------------+------+--------------------------------------------------------------------------------------------
 {{0.000 - 1.000}          |    0 |
  (1.000 - 2.778}          |    0 |
  (2.778 - 4.162}          |    0 |
  (4.162 - 6.623}          |    0 |
  (6.623 - 11.000}         |    0 |
  (11.000 - 18.783}        |    0 |
  (18.783 - 32.623}        |    0 |
  (32.623 - 57.234}        |    0 |
  (57.234 - 101.000}       |    0 |
  (101.000 - 178.827}      |    1 | ■■■■■■■■■■■■■■■
  (178.827 - 317.226}      |    0 |
  (317.226 - 563.338}      |    0 |
  (563.338 - 1000.994}     |    0 |
  (1000.994 - 1779.268}    |    1 | ■■■■■■■■■■■■■■■
  (1779.268 - 3163.256}    |    1 | ■■■■■■■■■■■■■■■
  (3163.256 - 5624.371}    |    1 | ■■■■■■■■■■■■■■■
  (5624.371 - 10000.920}   |    2 | ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  (10000.920 - 17783.643}  |    1 | ■■■■■■■■■■■■■■■
  (17783.643 - 31623.492}  |    0 |
  (31623.492 - 56234.598}  |    0 |
  (56234.598 - 100000.000} |    0 |
  (100000.000 - ...}}      |    0 |
(22 rows)

For pg_stat_monitor version 1.1.1 and earlier, the output shows the time generated automatically based on the total number of buckets in the resp_calls field which corresponds to the value specified by the user in the pgsm_histogram_buckets configuration parameter (defaults to 10).

Starting with version 2.0.0 the histogram output includes two additional buckets for queries whose execution time falls out of the min/max time range specified by the user. The first bucket starts with 0 and ends with the pgsm_histogram_min value. Another bucket starts from the pgsm_histogram_max time and lasts to the infinity.

These additional buckets enable users to see the how the data is distributed within the full range of values, not only the values specified within the min and max time range.

Note

Additional buckets are created only if:

  • the pgsm_histogram_min value is greater than 0
  • the pgsm_histogram_max value is less than the maximum possible value (2147483647)

The output shows to which bucket a value belongs to:

  • () show that the data is excluded form the range
  • {} indicate the data as included in the range.

For example, in the data range (1.000 - 2.778} and (2.778 - 4.162}, the value 2.778 belongs to the first bucket.

Get expert help

If you need assistance, visit the community forum for comprehensive and free database knowledge, or contact our Percona Database Experts for professional support and services.