Cómo saber que Query se esta ejecutando en PostgreSQL (Query Stats)

Algo muy común cuando se está trabajando en el mejoramiento del performance de los querys es saber cuales querys son los que están tomando más tiempo en ejecutarse, y ver cuales son los que más frecuentemente se ejecutan para considerar la posiblidad de almacenarlos en cache.

El problema es que cuando ya se está en ambiente de producción tener esta información es un poco complicada si no se conoce un poco de configuración del PostgreSQL.

En postgreSQL existe el archivo de configuración postgresql.conf de donde se leen las configuraciones iniciales.

En ese archivo hay muchas variables a configurar, pero específicamente una sección dedicada a las estadísticas.

#--------------------------------------------------------
# RUNTIME STATISTICS
#--------------------------------------------------------

# - Statistics Monitoring -

#log_parser_stats = off
#log_planner_stats = off
#log_executor_stats = off
#log_statement_stats = off

# - Query/Index Statistics Collector -

#stats_start_collector = on
stats_command_string = on
#stats_block_level = off
stats_row_level = on
#stats_reset_on_server_start = off

Por default la variable stats_command_string esta desáctivada, en las estadísticas no se permite ver el query que se ejecuta, sino simplemente aparece así:

 datid   |     datname   | procpid | usesysid |  usename |         current_query        |    query_start   |   backend_start  | client_addr    | client_port
---------+---------------+---------+----------+----------+------------------------------+------------------+------------------+----------------+-------------
58964727 | database1     |   31874 |    16384 | usuario1 | <command string not enabled> | 2007-11-29 14:51 | 2007-11-29 14:51 | 192.168.10.16  |  4096
58964727 | database1     |    3031 |    16384 | usuario1 | <command string not enabled> | 2007-11-29 22:02 | 2007-11-29 22:01 |                |    -1
58964727 | database1     |    3189 |  6191381 | rene     | <command string not enabled> | 2007-11-29 23:10 | 2007-11-29 23:09 | 192.168.10.109 |  4767
58964727 | database1     |   32157 |    16384 | usuario1 | <command string not enabled> | 2007-11-29 16:49 | 2007-11-29 15:16 | 192.168.10.16  |  2892
58964727 | database1     |    3190 |  6191381 | rene     | <command string not enabled> | 2007-11-29 23:11 | 2007-11-29 23:09 | 192.168.10.109 |  4775
35829649 | rene          |    3192 |  6191381 | rene     | <command string not enabled> | 2007-11-29 23:11 | 2007-11-29 23:11 |                |    -1

En cambio si activamos dicha variable stats_command_string = on, obtendremos:

  datid   |     datname   | procpid | usesysid |  usename |              current_query    |  query_start     | backend_start    |  client_addr   | client_port
----------+---------------+---------+----------+----------+-------------------------------+------------------+------------------+----------------+-------------
 58964727 | database1     |    3189 |  6191381 | rene     | <IDLE>                        | 2007-11-29 23:10 | 2007-11-29 23:09 | 192.168.10.109 |  4767
 58964727 | database1     |   32157 |    16384 | usuario1 | <IDLE>                        | 2007-11-29 16:49 | 2007-11-29 15:16 | 192.168.10.16  |  2892
 58964727 | database1     |    3190 |  6191381 | rene     | select to from tabla group to | 2007-11-29 23:11 | 2007-11-29 23:09 | 192.168.10.109 |  4775
 35829649 | rene          |    3192 |  6191381 | rene     | <IDLE>                        | 2007-11-29 23:11 | 2007-11-29 23:11 |                |    -1
    10793 | postgres      |     617 |  6191381 | rene     | <IDLE>                        | 2007-11-29 23:08 | 2007-11-29 16:42 | 192.168.10.109 |  1688
 35842383 | usuario1      |   30003 |    16384 | usuario1 | <IDLE>                        | 2007-11-29 12:20 | 2007-11-29 12:20 | 192.168.10.16  |  2555

De aquí podemos obtener cierta información para poder tomar desiciones sobre nuestros querys.

Les dejo el query que suelo utilizar yo cuando estoy revisando el tiempo que duran cada ejecución de un select por ejemplo

select procpid,current_query,
extract(minute from now()- query_start) ,
extract(second from now()- query_start)
from pg_stat_activity
where current_query ilike '%select%'
order by extract(minute from now()-query_start) desc;

Con este query puedo saber cuantos minutos y segundos llevan ejecutándose los querys.

Nota: Luego de cambiar el valor de la variable, no se olviden de reiniciar la Base de Datos, y no dejen activado dicho valor siempre, pues es una carga más a la BD que reducirá su rendimiento.

Espero que les sirva y como siempre, estamos en contacto!