{"id":32353,"date":"2019-10-31T21:46:32","date_gmt":"2019-10-31T18:46:32","guid":{"rendered":"https:\/\/prohoster.info\/blog\/monitoring-proizvoditelnosti-zaprosov-postgresql-chast-1-reporting\/"},"modified":"2019-10-31T21:46:32","modified_gmt":"2019-10-31T18:46:32","slug":"monitoring-proizvoditelnosti-zaprosov-postgresql-chast-1-reporting","status":"publish","type":"post","link":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/monitoring-proizvoditelnosti-zaprosov-postgresql-chast-1-reporting","title":{"rendered":"Monitoreo del rendimiento de las consultas de PostgreSQL. Parte 1 - reportes","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ingeniero - en traducci\u00f3n del lat\u00edn - inspirado.<br \/>\nEl ingeniero puede hacerlo todo. (c) R.Diesel.<br \/>\n<i>Ep\u00edgrafes.<\/i><br \/>\n<img decoding=\"async\" alt=\"Monitoreo del rendimiento de las consultas de PostgreSQL. Parte 1 - reportes\" src=\"\/wp-content\/uploads\/2019\/04\/9a2640267ea05006b94e03642b864ddc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>O la historia de por qu\u00e9 un administrador de bases de datos debe recordar su pasado como programador. <\/i><\/p>\n<h2>Pr\u00f3logo<\/h2>\n<p>\nTodos los nombres han sido cambiados. Las coincidencias son casuales. El material representa exclusivamente la opini\u00f3n personal del autor.<\/p>\n<blockquote><p><b>Descargo de responsabilidad:<\/b> <i>en el ciclo de art\u00edculos planeado no habr\u00e1 una descripci\u00f3n detallada y precisa de las tablas y scripts utilizados. Los materiales no podr\u00e1n ser utilizados de inmediato 'tal cual'. <br \/>\nPrimero, debido al gran volumen de material, <br \/>\ny, en segundo lugar, debido a la adaptaci\u00f3n con la base de producci\u00f3n del cliente real. <br \/>\nPor lo tanto, los art\u00edculos presentar\u00e1n solo ideas y descripciones de manera muy general. <br \/>\nQuiz\u00e1s en el futuro el sistema crecer\u00e1 hasta el nivel de subirlo a GitHub, o tal vez no. El tiempo lo dir\u00e1.<\/i><\/p><\/blockquote>\n<p>\nEl comienzo de la historia - '<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/icl_services\/blog\/446314\/\">\u00bfRecuerdas c\u00f3mo todo comenz\u00f3?<\/a><\/noindex>\u00bb.<br \/>\nQu\u00e9 se ha logrado como resultado, en las l\u00edneas m\u00e1s generales - '<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/444988\/\">La s\u00edntesis como uno de los m\u00e9todos para mejorar el rendimiento de PostgreSQL.<\/a><\/noindex>\u00bb<\/p>\n<h2>\u00bfPor qu\u00e9 me sirve todo esto?<\/h2>\n<p>\nBueno, primero, para no olvidarlo, recordando en la jubilaci\u00f3n esos gloriosos d\u00edas. <br \/>\nEn segundo lugar, para sistematizar lo escrito. Porque a veces yo mismo empiezo a confundir y olvidar partes individuales. <\/p>\n<p>Y lo m\u00e1s importante: quiz\u00e1s a alguien le sirva y ayude a no reinventar la rueda y no tropezar con las mismas piedras. En otras palabras, mejorar su karma (no el de Habr). Porque lo m\u00e1s valioso en este mundo son las ideas. Lo principal es encontrar una idea. Y llevar una idea a la realidad es solo una cuesti\u00f3n t\u00e9cnica.<\/p>\n<p>As\u00ed que, comencemos, poco a poco...<\/p>\n<h2>Planteamiento del problema.<\/h2>\n<p><\/p>\n<h3>Se tiene: <\/h3>\n<p>\nBase de datos PostgreSQL (10.5), de tipo de carga mixta (OLTP+DSS), de carga media-baja, ubicada en la nube de AWS. <br \/>\nEl monitoreo de la base de datos est\u00e1 ausente, el monitoreo de la infraestructura est\u00e1 representado por las herramientas est\u00e1ndar de AWS en configuraci\u00f3n m\u00ednima.<\/p>\n<h3>Requisitos:<\/h3>\n<p>\nMonitorear el rendimiento y estado de la base de datos, encontrar y tener informaci\u00f3n inicial para optimizar consultas pesadas a BDs.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Pre\u00e1mbulo breve o an\u00e1lisis de opciones de soluci\u00f3n<\/h2>\n<p>\nPara empezar, intentemos desglosar las opciones de soluci\u00f3n del problema desde el punto de vista del an\u00e1lisis comparativo de beneficios y desventajas para el ingeniero, mientras que los beneficios y p\u00e9rdidas de la gerencia que se ocupen aquellos a quienes les corresponde seg\u00fan el organigrama.<\/p>\n<h3>Opci\u00f3n 1 - 'Trabajando por demanda'<\/h3>\n<p>\nDejamos todo como est\u00e1. Si al cliente no le gusta algo en el funcionamiento, rendimiento de la base de datos o de la aplicaci\u00f3n, notificar\u00e1 a los ingenieros DBA por correo electr\u00f3nico o creando un incidente en el sistema de tickets. <br \/>\nEl ingeniero, al recibir la notificaci\u00f3n, se encargar\u00e1 del problema, propondr\u00e1 una soluci\u00f3n o pospondr\u00e1 el problema, esperando que todo se solucione por s\u00ed solo, ya que pronto se olvidar\u00e1.<br \/>\n<b class=\"spoiler_title\">Galletas y bu\u00f1uelos, contusiones y bultos.<\/b><b>Galletas y bu\u00f1uelos:<\/b><br \/>\n1. No hay que hacer nada innecesario.<br \/>\n2. Siempre hay una oportunidad de desentenderse y evadir responsabilidades. <br \/>\n3. Una gran cantidad de tiempo que se puede gastar a nuestro antojo.<br \/>\n<b>Contusiones y bultos:<\/b><br \/>\n1. Tarde o temprano, el cliente se preguntar\u00e1 sobre la esencia de la existencia y la justicia universal en este mundo, y una vez m\u00e1s se har\u00e1 la pregunta: \u00bfpor qu\u00e9 les estoy pagando mi dinero? La consecuencia siempre es la misma: solo hay que esperar a que el cliente se aburra y se despida. Y la fuente se agotar\u00e1. Es triste.<br \/>\n2. El desarrollo del ingeniero es nulo.<br \/>\n3. Dificultades en la planificaci\u00f3n del trabajo y la carga de trabajo. <\/p>\n<h3>Opci\u00f3n 2 - \"Bailamos con tambores, vendemos y calzamos.\"<\/h3>\n<p>\n<b>Punto 1<\/b>-\u00bfPara qu\u00e9 necesitamos un sistema de monitoreo? Vamos a recibir todo mediante solicitudes. Haremos un mont\u00f3n de solicitudes al diccionario de datos y a vistas din\u00e1micas, activaremos varios contadores, resumiremos todo en tablas, y de vez en cuando analizaremos listas y tablas. Como resultado, tendremos gr\u00e1ficos y tablas bonitos, o no tan bonitos. Lo importante es que sean muchos, muchos.<br \/>\n<b>Punto 2<\/b>-Generamos actividad, iniciamos el an\u00e1lisis de todo esto.<br \/>\n<b>Punto 3<\/b>-Preparamos un documento, llamamos a este documento, simplemente - \"c\u00f3mo debemos organizar la base de datos.\"<br \/>\n<b>Punto 4<\/b>-El cliente, al ver toda esta maravilla de gr\u00e1ficos y n\u00fameros, permanece en una ingenua confianza infantil - ahora todo funcionar\u00e1, pronto. Y f\u00e1cilmente y sin dolor se desprende de sus recursos financieros. La gerencia tambi\u00e9n est\u00e1 segura - nuestros ingenieros est\u00e1n trabajando mucho. La carga est\u00e1 al m\u00e1ximo. <br \/>\n<b>Punto 5<\/b>-Repetir regularmente el Punto 1.<br \/>\n<b class=\"spoiler_title\">Galletas y bu\u00f1uelos, contusiones y bultos.<\/b><b>Galletas y bu\u00f1uelos: <\/b><br \/>\n1. La vida de los gerentes y los ingenieros es simple, predecible y est\u00e1 llena de actividad. Todo zumbando, todos ocupados. <br \/>\n2. La vida del cliente tampoco es mala - siempre est\u00e1 seguro de que solo necesita esperar un poco y todo se resolver\u00e1. No se resuelve, bueno, qu\u00e9 le vamos a hacer, este mundo es injusto, en la pr\u00f3xima vida le tocar\u00e1.<br \/>\n<b>Contusiones y bultos:<\/b><br \/>\n1. Tarde o temprano, aparecer\u00e1 un proveedor m\u00e1s \u00e1gil de servicios similares que har\u00e1 lo mismo, pero un poco m\u00e1s barato. Y si el resultado es el mismo, \u00bfpor qu\u00e9 pagar m\u00e1s? Esto nuevamente llevar\u00e1 a la desaparici\u00f3n de la fuente de ingresos.<br \/>\n2. Es aburrido. Como lo es cualquier actividad poco significativa.<br \/>\n3. Al igual que en la opci\u00f3n anterior, no hay desarrollo. Pero para el ingeniero, hay una desventaja en que, a diferencia de la primera opci\u00f3n, aqu\u00ed se necesita generar constantemente la base de datos de informaci\u00f3n. Y eso consume tiempo. Tiempo que podr\u00eda gastarse en algo m\u00e1s beneficioso para uno mismo. Porque si no te cuidas, a nadie m\u00e1s le importa.<\/p>\n<h3>Opci\u00f3n 3: No es necesario reinventar la rueda, hay que comprarla y usarla.<\/h3>\n<p>\nLos ingenieros de otras empresas no comen pizza con cerveza sin raz\u00f3n (ah, buenos tiempos en San Petersburgo en los 90). Vamos a utilizar sistemas de monitoreo que ya est\u00e1n dise\u00f1ados, ajustados y en funcionamiento, y que, en general, aportan beneficios (bueno, al menos a sus creadores).<br \/>\n<b class=\"spoiler_title\">Galletas y bu\u00f1uelos, contusiones y bultos.<\/b><b>Galletas y bu\u00f1uelos:<\/b><br \/>\n1. No pierdas tiempo en inventar lo que ya ha sido creado. T\u00f3malo y \u00fasalo.<br \/>\n2. Los sistemas de monitoreo no son desarrollados por tontos y, por supuesto, son \u00fatiles.<br \/>\n3. Los sistemas de monitoreo operativos suelen proporcionar informaci\u00f3n \u00fatil y filtrada. <br \/>\n<b>Contusiones y bultos:<\/b><br \/>\n1. En este caso, el ingeniero no es ingeniero, sino simplemente un usuario de un producto ajeno. O un usuario.<br \/>\n2. Hay que convencer al cliente de la necesidad de comprar algo en lo que, en general, no quiere involucrarse, ni deber\u00eda; y el presupuesto para el a\u00f1o ya est\u00e1 aprobado y no cambiar\u00e1. Luego, hay que asignar recursos, ajustarlos a un sistema espec\u00edfico. Es decir, primero hay que pagar, pagar y volver a pagar. Y el cliente es taca\u00f1o. Eso es la norma de la vida.<\/p>\n<h2>\u00bfQu\u00e9 hacer, Chernyshevski? Tu pregunta es muy apropiada. (c)<\/h2>\n<p>\nEn este caso concreto y dadas las circunstancias, se puede actuar un poco diferente \u2014 <b>\u00bfY si hacemos nuestro propio sistema de monitoreo? <\/b><br \/>\n<img decoding=\"async\" alt=\"Monitoreo del rendimiento de las consultas de PostgreSQL. Parte 1 - reportes\" src=\"\/wp-content\/uploads\/2019\/04\/b59a3ad9e16b68c0fbc962a61d571c52.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nBueno, no un sistema en el verdadero sentido de la palabra, esto es demasiado fuerte y presuntuoso, pero al menos aliviar un poco la tarea y recopilar m\u00e1s informaci\u00f3n para resolver incidentes de rendimiento. Para no encontrarse en la situaci\u00f3n de 've all\u00e1, no s\u00e9 d\u00f3nde, encuentra eso, no s\u00e9 qu\u00e9'.<\/p>\n<h4>\u00bfCu\u00e1les son las ventajas y desventajas de esta opci\u00f3n?<\/h4>\n<p><b>Pros:<\/b><br \/>\n1. Es interesante. Al menos es m\u00e1s interesante que los constantes 'shrink datafile, alter tablespace, etc.'. <br \/>\n2. Estas son nuevas habilidades y un nuevo desarrollo. Que en el futuro, tarde o temprano, dar\u00e1 las recompensas y beneficios merecidos.<br \/>\n<b>Desventajas:<\/b><br \/>\n1. Tendremos que trabajar. Trabajar mucho. <br \/>\n2. Tendremos que explicar regularmente el significado y las perspectivas de toda la actividad.<br \/>\n3. Tendremos que sacrificar algo, ya que el \u00fanico recurso disponible para el ingeniero \u2014 el tiempo \u2014 est\u00e1 limitado por el universo. <br \/>\n<b>4. Lo m\u00e1s aterrador y desagradable<\/b> \u2014 como resultado, podr\u00eda salir algo como \"Ni rat\u00f3n, ni rana, sino una criatura desconocida.\"<\/p>\n<p><b>Qui\u00e9n no arriesga, no bebe champ\u00e1n.<\/b><br \/>\nAs\u00ed que \u2014 comienza lo m\u00e1s interesante.<\/p>\n<h2>La idea general \u2014 de manera esquem\u00e1tica<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Monitoreo del rendimiento de las consultas de PostgreSQL. Parte 1 - reportes\" src=\"\/wp-content\/uploads\/2019\/04\/d1ae2ddc1d4c43353fe93eebdaa8b81a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n(<i>La ilustraci\u00f3n fue tomada de un art\u00edculo<\/i> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/444988\/\">La s\u00edntesis como uno de los m\u00e9todos para mejorar el rendimiento de PostgreSQL.<\/a><\/noindex>\u00bb)<\/p>\n<p>Explicaci\u00f3n:<\/p>\n<ul>\n<li> En la base de datos objetivo se instala la extensi\u00f3n est\u00e1ndar de PostgreSQL \u2014 \"pg_stat_statements\". <\/li>\n<li>En la base de datos de monitoreo, creamos un conjunto de tablas de servicio para almacenar la historia de pg_stat_statements en la etapa inicial y para configurar m\u00e9tricas y monitoreo en el futuro.<\/li>\n<li> En el host de monitoreo, creamos un conjunto de scripts bash, incluyendo para la generaci\u00f3n de incidentes en el sistema de tickets. <\/li>\n<\/ul>\n<h2>Tablas de servicio<\/h2>\n<p>\nPara comenzar, un diagrama ERD simplificado, \u00bfqu\u00e9 es lo que se obtuvo al final?<br \/>\n<img decoding=\"async\" alt=\"Monitoreo del rendimiento de las consultas de PostgreSQL. Parte 1 - reportes\" src=\"\/wp-content\/uploads\/2019\/04\/03d29f4d6932d470d9d88651cbf0c715.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<b class=\"spoiler_title\">Descripci\u00f3n breve de las tablas<\/b><b>endpoint <\/b> \u2014 host, punto de conexi\u00f3n a la instancia<br \/>\n<b>database <\/b> \u2014 par\u00e1metros de la base de datos<br \/>\n<b>pg_stat_history <\/b> \u2014 tabla hist\u00f3rica para almacenar las instant\u00e1neas temporales de la vista pg_stat_statements de la base de datos objetivo<br \/>\n<b>metric_glossary <\/b> \u2014 glosario de m\u00e9tricas de rendimiento<br \/>\n<b>metric_config <\/b> \u2014 configuraci\u00f3n de m\u00e9tricas individuales<br \/>\n<b>metric <\/b> \u2014 m\u00e9trica espec\u00edfica para la consulta que se est\u00e1 monitoreando<br \/>\n<b>metric_alert_history <\/b> \u2014 historial de alertas de rendimiento<br \/>\n<b>log_query <\/b> \u2014 tabla de servicio para almacenar los registros analizados del archivo de log de PostgreSQL cargados desde AWS<br \/>\n<b>baseline <\/b> \u2014 par\u00e1metros de los per\u00edodos temporales utilizados como base <br \/>\n<b>checkpoint <\/b> \u2014 configuraci\u00f3n de las m\u00e9tricas de verificaci\u00f3n del estado de la base de datos<br \/>\n<b>checkpoint_alert_history <\/b> \u2014 historial de alertas de las m\u00e9tricas de verificaci\u00f3n del estado de la base de datos<br \/>\n<b>pg_stat_db_queries <\/b> \u2014 tabla de servicio para consultas activas <br \/>\n<b>activity_log <\/b> \u2014 tabla de servicio para el registro de actividades <br \/>\n<b>trap_oid <\/b> \u2014 tabla de servicio para la configuraci\u00f3n de trap<\/p>\n<p><\/p>\n<h2>Etapa 1 \u2014 recopilamos informaci\u00f3n estad\u00edstica sobre el rendimiento y obtenemos informes<\/h2>\n<p>\nLa tabla sirve para almacenar la informaci\u00f3n estad\u00edstica <b>pg_stat_history<\/b><br \/>\n<b class=\"spoiler_title\">Estructura de la tabla pg_stat_history<\/b><\/p>\n<pre>\n                                          Tabla \"public.pg_stat_history\"\n       Columna         |            Tipo             |                          Modificadores\n---------------------+-----------------------------+-------------------------------------------\n id                  | entero                     | no nulo por defecto nextval('pg_stat_history_id_seq'::regclass)\n snapshot_timestamp  | timestamp sin zona horaria |\n database_id         | entero                     |\n dbid                | oid                         |\n userid              | oid                         |\n queryid             | bigint                      |\n query               | texto                       |\n calls               | bigint                      |\n total_time          | doble precisi\u00f3n             |\n min_time            | doble precisi\u00f3n             |\n max_time            | doble precisi\u00f3n             |\n mean_time           | doble precisi\u00f3n             |\n stddev_time         | doble precisi\u00f3n             |\n rows                | bigint                      |\n shared_blks_hit     | bigint                      |\n shared_blks_read    | bigint                      |\n shared_blks_dirtied | bigint                      |\n shared_blks_written | bigint                      |\n local_blks_hit      | bigint                      |\n local_blks_read     | bigint                      |\n local_blks_dirtied  | bigint                      |\n local_blks_written  | bigint                      |\n temp_blks_read      | bigint                      |\n temp_blks_written   | bigint                      |\n blk_read_time       | doble precisi\u00f3n             |\n blk_write_time      | doble precisi\u00f3n             |\n baseline_id         | entero                     |\n\u00cdndices:\n    \"pg_stat_history_pkey\" CLAVE PRIMARIA, btree (id)\n    \"database_idx\" btree (database_id)\n    \"queryid_idx\" btree (queryid)\n    \"snapshot_timestamp_idx\" btree (snapshot_timestamp)\nRestricciones de clave for\u00e1nea:\n    \"database_id_fk\" CLAVE FOR\u00c1NEA (database_id) REFERENCIAS database(id) AL ELIMINAR CASCADA<\/pre>\n<p>\nComo se puede ver, la tabla es solo datos acumulativos de la vista <b>pg_stat_statements <\/b> en la base de datos de destino.<\/p>\n<h3>El uso de esta tabla es muy sencillo<\/h3>\n<p>\n<b>pg_stat_history<\/b> representar\u00e1 la estad\u00edstica acumulada de ejecuci\u00f3n de consultas por cada hora. Al inicio de cada hora, despu\u00e9s de llenar la tabla, la estad\u00edstica <b>pg_stat_statements<\/b> se restablece usando <b>pg_stat_statements_reset()<\/b>.<br \/>\nNota: <i>la estad\u00edstica se recopila para consultas con un tiempo de ejecuci\u00f3n superior a 1 segundo.<\/i><br \/>\n<b class=\"spoiler_title\">Llenado de la tabla pg_stat_history<\/b><\/p>\n<pre><code class=\"plaintext\">--pg_stat_history.sql\nCREATE OR REPLACE FUNCTION pg_stat_history( ) RETURNS boolean AS $$\nDECLARE\n  endpoint_rec record ;\n  database_rec record ;\n  pg_stat_snapshot record ;\n  current_snapshot_timestamp timestamp without time zone;\nBEGIN\n  current_snapshot_timestamp = date_trunc('minute',now());  \n  \n  FOR endpoint_rec IN SELECT * FROM endpoint \n  LOOP\n    FOR database_rec IN SELECT * FROM database WHERE endpoint_id = endpoint_rec.id \n\t  LOOP\n\t    \n\t\tRAISE NOTICE 'SE EST\u00c1 CREANDO UN NUEVO GRUPO';\n\t\t\n\t\t--Conectarse a la base de datos objetivo\t  \n\t    EXECUTE 'SELECT dblink_connect(''LINK1'',''host='||endpoint_rec.host||' dbname='||database_rec.name||' user=USER password=PASSWORD '')';\n \n        RAISE NOTICE 'host % y dbname % ',endpoint_rec.host,database_rec.name;\n\t\tRAISE NOTICE 'Creando grupo de pg_stat_statements para la base de datos %',database_rec.name;\n\t\t\n\t\tSELECT \n\t      *\n\t\tINTO \n\t\t  pg_stat_snapshot\n\t    FROM dblink('LINK1',\n\t      'SELECT \n\t       dbid , SUM(calls),SUM(total_time),SUM(rows) ,SUM(shared_blks_hit) ,SUM(shared_blks_read) ,SUM(shared_blks_dirtied) ,SUM(shared_blks_written) , \n           SUM(local_blks_hit) , SUM(local_blks_read) , SUM(local_blks_dirtied) , SUM(local_blks_written) , SUM(temp_blks_read) , SUM(temp_blks_written) , SUM(blk_read_time) , SUM(blk_write_time)\n\t       FROM pg_stat_statements WHERE dbid=(SELECT oid from pg_database where datname=current_database() ) \n\t\t   GROUP BY dbid\n  \t      '\n\t               )\n\t      AS t\n\t       ( dbid oid , calls bigint , \n  \t         total_time double precision , \n\t         rows bigint , shared_blks_hit bigint , shared_blks_read bigint ,shared_blks_dirtied bigint ,shared_blks_written\t bigint ,\n             local_blks_hit\t bigint ,local_blks_read bigint , local_blks_dirtied bigint ,local_blks_written bigint ,\n             temp_blks_read\t bigint ,temp_blks_written bigint ,\n             blk_read_time double precision , blk_write_time double precision\t  \n\t       );\n\t\t \n\t\tINSERT INTO pg_stat_history\n          ( \n\t\t    snapshot_timestamp  ,database_id  ,\n\t\t\tdbid , calls  ,total_time ,\n            rows ,shared_blks_hit  ,shared_blks_read  ,shared_blks_dirtied  ,shared_blks_written ,local_blks_hit , \t \t\n            local_blks_read,local_blks_dirtied,local_blks_written,temp_blks_read,temp_blks_written, \t\n            blk_read_time, blk_write_time \n\t\t  )\t\t  \n\t    VALUES\n\t      (\n\t       current_snapshot_timestamp ,\n\t\t   database_rec.id ,\n\t       pg_stat_snapshot.dbid ,pg_stat_snapshot.calls,\n\t       pg_stat_snapshot.total_time,\n\t       pg_stat_snapshot.rows ,pg_stat_snapshot.shared_blks_hit ,pg_stat_snapshot.shared_blks_read ,pg_stat_snapshot.shared_blks_dirtied ,pg_stat_snapshot.shared_blks_written , \n           pg_stat_snapshot.local_blks_hit , pg_stat_snapshot.local_blks_read , pg_stat_snapshot.local_blks_dirtied , pg_stat_snapshot.local_blks_written , \n\t       pg_stat_snapshot.temp_blks_read , pg_stat_snapshot.temp_blks_written , pg_stat_snapshot.blk_read_time , pg_stat_snapshot.blk_write_time \t   \n\t      );\t\t   \n\t\t  \n        RAISE NOTICE 'Creando grupo de pg_stat_statements para consultas con min_time mayor a 1000ms';\n\t\n        FOR pg_stat_snapshot IN\n          --Todas las consultas con max_time superior a 1000 ms\n\t      SELECT \n\t        *\n\t      FROM dblink('LINK1',\n\t        'SELECT \n\t         dbid , userid ,queryid,query,calls,total_time,min_time ,max_time,mean_time, stddev_time ,rows ,shared_blks_hit ,\n\t\t\t shared_blks_read ,shared_blks_dirtied ,shared_blks_written , \n             local_blks_hit , local_blks_read , local_blks_dirtied , \n\t\t\t local_blks_written , temp_blks_read , temp_blks_written , blk_read_time , \n\t\t\t blk_write_time\n\t         FROM pg_stat_statements \n\t\t\t WHERE dbid=(SELECT oid from pg_database where datname=current_database() AND min_time &gt;= 1000 ) \n  \t        '\n\n\t                  )\n\t        AS t\n\t         ( dbid oid , userid oid , queryid bigint ,query text , calls bigint , \n  \t           total_time double precision ,min_time double precision\t ,max_time double precision\t , mean_time double precision\t ,  stddev_time double precision\t , \n\t           rows bigint , shared_blks_hit bigint , shared_blks_read bigint ,shared_blks_dirtied bigint ,shared_blks_written\t bigint ,\n               local_blks_hit\t bigint ,local_blks_read bigint , local_blks_dirtied bigint ,local_blks_written bigint ,\n               temp_blks_read\t bigint ,temp_blks_written bigint ,\n               blk_read_time double precision , blk_write_time double precision\t  \n\t         )\n\t    LOOP\n\t\t  INSERT INTO pg_stat_history\n          ( \n\t\t    snapshot_timestamp  ,database_id  ,\n\t\t\tdbid ,userid  , queryid  , query  , calls  ,total_time ,min_time ,max_time ,mean_time ,stddev_time ,\n            rows ,shared_blks_hit  ,shared_blks_read  ,shared_blks_dirtied  ,shared_blks_written ,local_blks_hit , \t \t\n            local_blks_read,local_blks_dirtied,local_blks_written,temp_blks_read,temp_blks_written, \t\n            blk_read_time, blk_write_time \n\t\t  )\t\t  \n\t      VALUES\n\t      (\n\t       current_snapshot_timestamp ,\n\t\t   database_rec.id ,\n\t       pg_stat_snapshot.dbid ,pg_stat_snapshot.userid ,pg_stat_snapshot.queryid,pg_stat_snapshot.query,pg_stat_snapshot.calls,\n\t       pg_stat_snapshot.total_time,pg_stat_snapshot.min_time ,pg_stat_snapshot.max_time,pg_stat_snapshot.mean_time, pg_stat_snapshot.stddev_time ,\n\t       pg_stat_snapshot.rows ,pg_stat_snapshot.shared_blks_hit ,pg_stat_snapshot.shared_blks_read ,pg_stat_snapshot.shared_blks_dirtied ,pg_stat_snapshot.shared_blks_written , \n           pg_stat_snapshot.local_blks_hit , pg_stat_snapshot.local_blks_read , pg_stat_snapshot.local_blks_dirtied , pg_stat_snapshot.local_blks_written , \n\t       pg_stat_snapshot.temp_blks_read , pg_stat_snapshot.temp_blks_written , pg_stat_snapshot.blk_read_time , pg_stat_snapshot.blk_write_time \t   \n\t      );\n\t\t  \n        END LOOP;\n\n        PERFORM dblink_disconnect('LINK1');  \n\t\t\t\t\n\t  END LOOP ;--FOR database_rec IN SELECT * FROM database WHERE endpoint_id = endpoint_rec.id \n    \n  END LOOP;\n\nRETURN TRUE;  \nEND\n$$ LANGUAGE plpgsql;<\/code><\/pre>\n<p>Como resultado, despu\u00e9s de un tiempo en la tabla <b>pg_stat_history<\/b> tendremos un conjunto de instant\u00e1neas del contenido de la tabla <b>pg_stat_statements <\/b>de la base de datos objetivo. <\/p>\n<h2>Generaci\u00f3n de informes<\/h2>\n<p>\nUsando consultas simples, se pueden obtener informes bastante \u00fatiles e interesantes.<\/p>\n<h2>Datos agregados durante un per\u00edodo de tiempo espec\u00edfico<\/h2>\n<p><b class=\"spoiler_title\">Consulta<\/b><\/p>\n<pre><code class=\"plaintext\">SELECT \n  database_id , \n  SUM(calls) AS calls ,SUM(total_time)  AS total_time ,\n  SUM(rows) AS rows , SUM(shared_blks_hit)  AS shared_blks_hit,\n  SUM(shared_blks_read) AS shared_blks_read ,\n  SUM(shared_blks_dirtied) AS shared_blks_dirtied,\n  SUM(shared_blks_written) AS shared_blks_written , \n  SUM(local_blks_hit) AS local_blks_hit , \n  SUM(local_blks_read) AS local_blks_read , \n  SUM(local_blks_dirtied) AS local_blks_dirtied , \n  SUM(local_blks_written)  AS local_blks_written,\n  SUM(temp_blks_read) AS temp_blks_read, \n  SUM(temp_blks_written) temp_blks_written , \n  SUM(blk_read_time) AS blk_read_time , \n  SUM(blk_write_time) AS blk_write_time\nFROM \n  pg_stat_history\nWHERE \n  queryid IS NULL AND\n  database_id = DATABASE_ID  AND\n  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT\nGROUP BY database_id ;<\/code><\/pre>\n<p><\/p>\n<h4>Tiempo de DB<\/h4>\n<blockquote><p>to_char(interval '1 millisecond' * pg_total_stat_history_rec.total_time, 'HH24:MI:SS.MS')<\/p><\/blockquote>\n<p><\/p>\n<h4>Tiempo de I\/O<\/h4>\n<blockquote><p>to_char(interval '1 millisecond' * (pg_total_stat_history_rec.blk_read_time + pg_total_stat_history_rec.blk_write_time), 'HH24:MI:SS.MS')<\/p><\/blockquote>\n<h3>TOP10 SQL por total_time<\/h3>\n<p><b class=\"spoiler_title\">Consulta<\/b><\/p>\n<pre><code class=\"plaintext\">SELECT \n  queryid , \n  SUM(calls) AS calls ,\n  SUM(total_time)  AS total_time  \t\nFROM \n  pg_stat_history\nWHERE \n  queryid IS NOT NULL AND \n  database_id = DATABASE_ID AND\n  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT \nGROUP BY queryid \nORDER BY 3 DESC \nLIMIT 10<\/code><\/pre>\n<pre>-------------------------------------------------------------------------------------\n| TOP10 SQL POR TIEMPO TOTAL DE EJECUCI\u00d3N\n|   #|    queryid|      calls|    % de llamadas|                tiempo_total (ms) |  % dbtime\n+----+-----------+-----------+-----------+--------------------------------+----------\n|   1|  821760255|          2|     .00001|00:03:23.141(    203141.681 ms.)|      5.42\n|   2| 4152624390|          2|     .00001|00:03:13.929(    193929.215 ms.)|      5.17\n|   3| 1484454471|          4|     .00001|00:02:09.129(    129129.057 ms.)|      3.44\n|   4|  655729273|          1|     .00000|00:02:01.869(    121869.981 ms.)|      3.25\n|   5| 2460318461|          1|     .00000|00:01:33.113(     93113.835 ms.)|      2.48\n|   6| 2194493487|          4|     .00001|00:00:17.377(     17377.868 ms.)|       .46\n|   7| 1053044345|          1|     .00000|00:00:06.156(      6156.352 ms.)|       .16\n|   8| 3644780286|          1|     .00000|00:00:01.063(      1063.830 ms.)|       .03\n<\/pre>\n<h4>TOP10 SQL por tiempo total de I\/O<\/h4>\n<p><b class=\"spoiler_title\">Consulta<\/b><\/p>\n<pre><code class=\"plaintext\">SELECT \n  queryid , \n  SUM(calls) AS calls ,\n  SUM(blk_read_time + blk_write_time)  AS io_time\nFROM \n  pg_stat_history\nWHERE \n  queryid IS NOT NULL AND \n  database_id = DATABASE_ID  AND\n  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT\nGROUP BY  queryid \nORDER BY 3 DESC \nLIMIT 10<\/code><\/pre>\n<pre>----------------------------------------------------------------------------------------\n| TOP10 SQL POR TIEMPO TOTAL DE I\/O\n|   #|    queryid|      llamadas|    % de llamadas|                   Tiempo I\/O (ms)|% de tiempo de I\/O de la base de datos\n+----+-----------+-----------+-----------+--------------------------------+-------------\n|   1| 4152624390|          2|     .00001|00:08:31.616(    511616.592 ms.)|        31.06\n|   2|  821760255|          2|     .00001|00:08:27.099(    507099.036 ms.)|        30.78\n|   3|  655729273|          1|     .00000|00:05:02.209(    302209.137 ms.)|        18.35\n|   4| 2460318461|          1|     .00000|00:04:05.981(    245981.117 ms.)|        14.93\n|   5| 1484454471|          4|     .00001|00:00:39.144(     39144.221 ms.)|         2.38\n|   6| 2194493487|          4|     .00001|00:00:18.182(     18182.816 ms.)|         1.10\n|   7| 1053044345|          1|     .00000|00:00:16.611(     16611.722 ms.)|         1.01\n|   8| 3644780286|          1|     .00000|00:00:00.436(       436.205 ms.)|          .03\n<\/pre>\n<h4>TOP10 SQL por tiempo m\u00e1ximo de ejecuci\u00f3n<\/h4>\n<p><b class=\"spoiler_title\">Consulta<\/b><\/p>\n<pre><code class=\"plaintext\">SELECT \n  id AS snapshotid , \n  queryid , \n  snapshot_timestamp ,  \n  max_time \nFROM \n  pg_stat_history \nWHERE \n  queryid IS NOT NULL AND \n  database_id = DATABASE_ID  AND\n  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT\nORDER BY 4 DESC \nLIMIT 10<\/code><\/pre>\n<p><\/p>\n<pre>-----------------------------------------------------------------------------------------\n| TOP10 SQL POR TIEMPO M\u00c1XIMO DE EJECUCI\u00d3N\n|   #|          snapshot| snapshotID|    queryid|                           max_time (ms)\n+----+------------------+-----------+-----------+----------------------------------------\n|   1|  05.04.2019 01:03|       4169|  655729273|        00:02:01.869(    121869.981 ms.)\n|   2|  04.04.2019 17:00|       4153|  821760255|        00:01:41.570(    101570.841 ms.)\n|   3|  04.04.2019 16:00|       4146|  821760255|        00:01:41.570(    101570.841 ms.)\n|   4|  04.04.2019 16:00|       4144| 4152624390|        00:01:36.964(     96964.607 ms.)\n|   5|  04.04.2019 17:00|       4151| 4152624390|        00:01:36.964(     96964.607 ms.)\n|   6|  05.04.2019 10:00|       4188| 1484454471|        00:01:33.452(     93452.150 ms.)\n|   7|  04.04.2019 17:00|       4150| 2460318461|        00:01:33.113(     93113.835 ms.)\n|   8|  04.04.2019 15:00|       4140| 1484454471|        00:00:11.892(     11892.302 ms.)\n|   9|  04.04.2019 16:00|       4145| 1484454471|        00:00:11.892(     11892.302 ms.)\n|  10|  04.04.2019 17:00|       4152| 1484454471|        00:00:11.892(     11892.302 ms.)\n<\/pre>\n<h4>TOP10 SQL por lectura\/escritura en buffer compartido<\/h4>\n<p><b class=\"spoiler_title\">Consulta<\/b><\/p>\n<pre><code class=\"plaintext\">SELECT \n  id AS snapshotid , \n  queryid ,\n  snapshot_timestamp , \n  shared_blks_read , \n  shared_blks_written \nFROM \n  pg_stat_history\nWHERE \n  queryid IS NOT NULL AND \n  database_id = DATABASE_ID  AND\n  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT AND\n  ( shared_blks_read &gt; 0 OR shared_blks_written &gt; 0 )\nORDER BY 4 DESC  , 5 DESC \nLIMIT 10<\/code><\/pre>\n<pre>--------------------------------------------------------------------------------------------\n| TOP10 SQL POR LECTURA\/ESCRITURA DE BUFFER COMPARTIDO\n|   #|          instant\u00e1nea| snapshotID|    queryid|   bloques compartidos le\u00eddos|  bloques compartidos escritos\n+----+------------------+-----------+-----------+---------------------+---------------------\n|   1|  04.04.2019 17:00|       4153|  821760255|               797308|                    0\n|   2|  04.04.2019 16:00|       4146|  821760255|               797308|                    0\n|   3|  05.04.2019 01:03|       4169|  655729273|               797158|                    0\n|   4|  04.04.2019 16:00|       4144| 4152624390|               756514|                    0\n|   5|  04.04.2019 17:00|       4151| 4152624390|               756514|                    0\n|   6|  04.04.2019 17:00|       4150| 2460318461|               734117|                    0\n|   7|  04.04.2019 17:00|       4155| 3644780286|                52973|                    0\n|   8|  05.04.2019 01:03|       4168| 1053044345|                52818|                    0\n|   9|  04.04.2019 15:00|       4141| 2194493487|                52813|                    0\n|  10|  04.04.2019 16:00|       4147| 2194493487|                52813|                    0\n--------------------------------------------------------------------------------------------\n<\/pre>\n<h4>Histograma de distribuci\u00f3n de consultas por el tiempo m\u00e1ximo de ejecuci\u00f3n<\/h4>\n<p><b class=\"spoiler_title\">Consultas<\/b><\/p>\n<pre><code class=\"plaintext\">SELECT  \n  MIN(max_time) AS hist_min  , \n  MAX(max_time) AS hist_max , \n  (( MAX(max_time) - MIN(min_time) ) \/ hist_columns ) as hist_width\nFROM \n  pg_stat_history \nWHERE \n  queryid IS NOT NULL AND\n  database_id = DATABASE_ID  AND\n  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT ;\n\nSELECT \n  SUM(calls) AS calls\nFROM \n  pg_stat_history \nWHERE \n  queryid IS NOT NULL AND\n  database_id =DATABASE_ID  AND\n  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT AND \n  ( max_time &gt;= hist_current_min AND  max_time &lt; hist_current_max ) ;\n<\/code><\/pre>\n<pre>|-----------------------------------------------------------------------------------------------\n| HISTOGRAMA DE MAX_TIME\n| TOTAL DE LLAMADAS : 33851920\n| TIEMPO M\u00cdNIMO  : 00:00:01.063\n| TIEMPO M\u00c1XIMO  : 00:02:01.869\n---------------------------------------------------------------------------------\n|                      duraci\u00f3n m\u00ednima|                      duraci\u00f3n m\u00e1xima|     llamadas\n+----------------------------------+----------------------------------+----------\n| 00:00:01.063(      1063.830 ms.) | 00:00:13.144(     13144.445 ms.) | 9\n| 00:00:13.144(     13144.445 ms.) | 00:00:25.225(     25225.060 ms.) | 0\n| 00:00:25.225(     25225.060 ms.) | 00:00:37.305(     37305.675 ms.) | 0\n| 00:00:37.305(     37305.675 ms.) | 00:00:49.386(     49386.290 ms.) | 0\n| 00:00:49.386(     49386.290 ms.) | 00:01:01.466(     61466.906 ms.) | 0\n| 00:01:01.466(     61466.906 ms.) | 00:01:13.547(     73547.521 ms.) | 0\n| 00:01:13.547(     73547.521 ms.) | 00:01:25.628(     85628.136 ms.) | 0\n| 00:01:25.628(     85628.136 ms.) | 00:01:37.708(     97708.751 ms.) | 4\n| 00:01:37.708(     97708.751 ms.) | 00:01:49.789(    109789.366 ms.) | 2\n| 00:01:49.789(    109789.366 ms.) | 00:02:01.869(    121869.981 ms.) | 0\n<\/pre>\n<h4>TOP10 Instant\u00e1neas por Consulta por Segundo<\/h4>\n<p><b class=\"spoiler_title\">Consultas<\/b><\/p>\n<pre><code class=\"plaintext\">--pg_qps.sql\n--Calcular Consultas Por Segundo \nCREATE OR REPLACE FUNCTION pg_qps( pg_stat_history_id integer ) RETURNS double precision AS $$\nDECLARE\n pg_stat_history_rec record ;\n prev_pg_stat_history_id integer ;\n prev_pg_stat_history_rec record;\n total_seconds double precision ;\n result double precision;\nBEGIN \n  result = 0 ;\n  \n  SELECT *\n  INTO pg_stat_history_rec\n  FROM \n    pg_stat_history\n  WHERE id = pg_stat_history_id ;\n\n  IF pg_stat_history_rec.snapshot_timestamp IS NULL \n  THEN\n    RAISE EXCEPTION 'ERROR - No se encontr\u00f3 pg_stat_history para id = %',pg_stat_history_id;\n  END IF ;  \n  \n --RAISE NOTICE 'pg_stat_history_id = % , snapshot_timestamp = %', pg_stat_history_id , \n pg_stat_history_rec.snapshot_timestamp ;\n  \n  SELECT \n    MAX(id)   \n  INTO\n    prev_pg_stat_history_id\n  FROM\n    pg_stat_history\n  WHERE \n    database_id = pg_stat_history_rec.database_id AND\n\tqueryid IS NULL AND\n\tid  0 \n  THEN\n    result = pg_stat_history_rec.calls \/ total_seconds ;\n  ELSE\n   result = 0 ; \n  END IF;\n   \n RETURN result ;\nEND\n$$ LANGUAGE plpgsql;\n\n\nSELECT \n  id , \n  snapshot_timestamp ,\n  calls , \t\n  total_time , \n  ( select pg_qps( id )) AS QPS ,\n  blk_read_time ,\n  blk_write_time\nFROM \n  pg_stat_history\nWHERE \n  queryid IS NULL AND \n  database_id = DATABASE_ID  AND\n  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT AND\n  ( select pg_qps( id )) IS NOT NULL \nORDER BY 5 DESC \nLIMIT 10\n<\/code><\/pre>\n<pre>|-----------------------------------------------------------------------------------------------\n| TOP10 Instant\u00e1neas ordenadas por n\u00fameros de QueryPerSeconds\n-----------------------------------------------------------------------------------------------------------------------------------------------\n|    #|          instant\u00e1nea| snapshotID|      llamadas|                      tiempo total db|        QPS|                          tiempo I\/O| % tiempo I\/O\n+-----+------------------+-----------+-----------+----------------------------------+-----------+----------------------------------+-----------\n|    1|  04.04.2019 20:04|       4161|    5758631|  00:06:30.513(    390513.926 ms.)|   1573.396|  00:00:01.470(      1470.110 ms.)|       .376\n|    2|  04.04.2019 17:00|       4149|    3529197|  00:11:48.830(    708830.618 ms.)|    980.332|  00:12:47.834(    767834.052 ms.)|    108.324\n|    3|  04.04.2019 16:00|       4143|    3525360|  00:10:13.492(    613492.351 ms.)|    979.267|  00:08:41.396(    521396.555 ms.)|     84.988\n|    4|  04.04.2019 21:03|       4163|    2781536|  00:03:06.470(    186470.979 ms.)|    785.745|  00:00:00.249(       249.865 ms.)|       .134\n|    5|  04.04.2019 19:03|       4159|    2890362|  00:03:16.784(    196784.755 ms.)|    776.979|  00:00:01.441(      1441.386 ms.)|       .732\n|    6|  04.04.2019 14:00|       4137|    2397326|  00:04:43.033(    283033.854 ms.)|    665.924|  00:00:00.024(        24.505 ms.)|       .009\n|    7|  04.04.2019 15:00|       4139|    2394416|  00:04:51.435(    291435.010 ms.)|    665.116|  00:00:12.025(     12025.895 ms.)|      4.126\n|    8|  04.04.2019 13:00|       4135|    2373043|  00:04:26.791(    266791.988 ms.)|    659.179|  00:00:00.064(        64.261 ms.)|       .024\n|    9|  05.04.2019 01:03|       4167|    4387191|  00:06:51.380(    411380.293 ms.)|    609.332|  00:05:18.847(    318847.407 ms.)|     77.507\n|   10|  04.04.2019 18:01|       4157|    1145596|  00:01:19.217(     79217.372 ms.)|    313.004|  00:00:01.319(      1319.676 ms.)|      1.666\n<\/pre>\n<h4>Registro de Ejecuci\u00f3n Horaria con QueryPerSeconds y Tiempo I\/O<\/h4>\n<p><b class=\"spoiler_title\">Consulta<\/b><\/p>\n<pre><code class=\"plaintext\">SELECT \n  id , \n  snapshot_timestamp ,\n  llamadas , \t\n  tiempo_total , \n  ( select pg_qps( id )) AS QPS ,\n  blk_read_time ,\n  blk_write_time\nFROM \n  pg_stat_history\nWHERE \n  queryid IS NULL AND \n  database_id = DATABASE_ID  AND\n  snapshot_timestamp BETWEEN BEGIN_TIMEPOINT AND END_TIMEPOINT\nORDER BY 2\n<\/code><\/pre>\n<pre>|-----------------------------------------------------------------------------------------------\n| HISTORIAL DE EJECUCI\u00d3N POR HORA CON QueryPerSeconds y Tiempo de I\/O\n-----------------------------------------------------------------------------------------------------------------------------------------------\n| HISTORIAL DE CONSULTAS POR SEGUNDO\n|    #|          instant\u00e1nea| snapshotID|      llamadas|                      tiempo total db|        QPS|                          tiempo de I\/O| % de tiempo de I\/O\n+-----+------------------+-----------+-----------+----------------------------------+-----------+----------------------------------+-----------\n|    1|  04.04.2019 11:00|       4131|       3747|  00:00:00.835(       835.374 ms.)|      1.041|  00:00:00.000(          .000 ms.)|       .000\n|    2|  04.04.2019 12:00|       4133|    1002722|  00:01:52.419(    112419.376 ms.)|    278.534|  00:00:00.149(       149.105 ms.)|       .133\n|    3|  04.04.2019 13:00|       4135|    2373043|  00:04:26.791(    266791.988 ms.)|    659.179|  00:00:00.064(        64.261 ms.)|       .024\n|    4|  04.04.2019 14:00|       4137|    2397326|  00:04:43.033(    283033.854 ms.)|    665.924|  00:00:00.024(        24.505 ms.)|       .009\n|    5|  04.04.2019 15:00|       4139|    2394416|  00:04:51.435(    291435.010 ms.)|    665.116|  00:00:12.025(     12025.895 ms.)|      4.126\n|    6|  04.04.2019 16:00|       4143|    3525360|  00:10:13.492(    613492.351 ms.)|    979.267|  00:08:41.396(    521396.555 ms.)|     84.988\n|    7|  04.04.2019 17:00|       4149|    3529197|  00:11:48.830(    708830.618 ms.)|    980.332|  00:12:47.834(    767834.052 ms.)|    108.324\n|    8|  04.04.2019 18:01|       4157|    1145596|  00:01:19.217(     79217.372 ms.)|    313.004|  00:00:01.319(      1319.676 ms.)|      1.666\n|    9|  04.04.2019 19:03|       4159|    2890362|  00:03:16.784(    196784.755 ms.)|    776.979|  00:00:01.441(      1441.386 ms.)|       .732\n|   10|  04.04.2019 20:04|       4161|    5758631|  00:06:30.513(    390513.926 ms.)|   1573.396|  00:00:01.470(      1470.110 ms.)|       .376\n|   11|  04.04.2019 21:03|       4163|    2781536|  00:03:06.470(    186470.979 ms.)|    785.745|  00:00:00.249(       249.865 ms.)|       .134\n|   12|  04.04.2019 23:03|       4165|    1443155|  00:01:34.467(     94467.539 ms.)|    200.438|  00:00:00.015(        15.287 ms.)|       .016\n|   13|  05.04.2019 01:03|       4167|    4387191|  00:06:51.380(    411380.293 ms.)|    609.332|  00:05:18.847(    318847.407 ms.)|     77.507\n|   14|  05.04.2019 02:03|       4171|     189852|  00:00:10.989(     10989.899 ms.)|     52.737|  00:00:00.539(       539.110 ms.)|      4.906\n|   15|  05.04.2019 03:01|       4173|       3627|  00:00:00.103(       103.000 ms.)|      1.042|  00:00:00.004(         4.131 ms.)|      4.010\n|   16|  05.04.2019 04:00|       4175|       3627|  00:00:00.085(        85.235 ms.)|      1.025|  00:00:00.003(         3.811 ms.)|      4.471\n|   17|  05.04.2019 05:00|       4177|       3747|  00:00:00.849(       849.454 ms.)|      1.041|  00:00:00.006(         6.124 ms.)|       .721\n|   18|  05.04.2019 06:00|       4179|       3747|  00:00:00.849(       849.561 ms.)|      1.041|  00:00:00.000(          .051 ms.)|       .006\n|   19|  05.04.2019 07:00|       4181|       3747|  00:00:00.839(       839.416 ms.)|      1.041|  00:00:00.000(          .062 ms.)|       .007\n|   20|  05.04.2019 08:00|       4183|       3747|  00:00:00.846(       846.382 ms.)|      1.041|  00:00:00.000(          .007 ms.)|       .001\n|   21|  05.04.2019 09:00|       4185|       3747|  00:00:00.855(       855.426 ms.)|      1.041|  00:00:00.000(          .065 ms.)|       .008\n|   22|  05.04.2019 10:00|       4187|       3797|  00:01:40.150(    100150.165 ms.)|      1.055|  00:00:21.845(     21845.217 ms.)|     21.812\n<\/pre>\n<h4>Texto de todas las selecciones SQL<\/h4>\n<p><b class=\"spoiler_title\">Consulta<\/b><\/p>\n<pre><code class=\"plaintext\">SELECCIONAR \n  queryid , \n  query \nDE \n  pg_stat_history\nDONDE \n  queryid NO ES NULO Y \n  database_id = DATABASE_ID Y\n  snapshot_timestamp ENTRE BEGIN_TIMEPOINT Y END_TIMEPOINT\nAGRUPAR POR queryid , query\n<\/code><\/pre>\n<h2>Summary<\/h2>\n<p>\nComo se puede ver, con recursos bastante simples, se puede obtener mucha informaci\u00f3n \u00fatil sobre la carga y el estado de la base de datos. <\/p>\n<p><b>Nota:<\/b>Si registramos queryid en las consultas, obtendremos el historial de una consulta espec\u00edfica (por razones de ahorro de espacio, los informes para consultas individuales se omiten).<\/p>\n<p>As\u00ed que, los datos estad\u00edsticos sobre el rendimiento de las consultas est\u00e1n disponibles y se est\u00e1n recopilando.<br \/>\nLa primera etapa \"recogida de datos estad\u00edsticos\" ha concluido.<\/p>\n<p>Ahora podemos pasar a la segunda etapa: \"ajuste de m\u00e9tricas de rendimiento\".<br \/>\n<img decoding=\"async\" alt=\"Monitoreo del rendimiento de las consultas de PostgreSQL. Parte 1 - reportes\" src=\"\/wp-content\/uploads\/2019\/04\/a893e49280d4cb425e4667a5c51d2397.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Pero esa es otra historia completamente diferente.<\/b><\/p>\n<p><i>Continuar\u00e1...<\/i><br \/>\n<br \/>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/icl_services\/blog\/446734\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0418\u043d\u0436\u0435\u043d\u0435\u0440 \u2014 \u0432 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0435 \u0441 \u043b\u0430\u0442\u044b\u043d\u0438 \u2014 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0435\u043d\u043d\u044b\u0439. \u0418\u043d\u0436\u0435\u043d\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0432\u0441\u0451. (\u0441) \u0420.\u0414\u0438\u0437\u0435\u043b\u044c. \u042d\u043f\u0438\u0433\u0440\u0430\u0444\u044b. \u0418\u043b\u0438 \u0438\u0441\u0442\u043e\u0440\u0438\u044f \u043e \u0442\u043e\u043c, \u0437\u0430\u0447\u0435\u043c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0443 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0441\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c \u0441\u0432\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u043e\u0448\u043b\u043e\u0435. \u041f\u0440\u0435\u0434\u0438\u0441\u043b\u043e\u0432\u0438\u0435 \u0412\u0441\u0435 \u0438\u043c\u0435\u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u044b. \u0421\u043e\u0432\u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b. \u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043b\u0438\u0447\u043d\u043e\u0435 \u043c\u043d\u0435\u043d\u0438\u0435 \u0430\u0432\u0442\u043e\u0440\u0430. Disclaimer of warranties: \u0432 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u043c\u043e\u043c \u0446\u0438\u043a\u043b\u0435 \u0441\u0442\u0430\u0442\u0435\u0439 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0433\u043e \u0438 \u0442\u043e\u0447\u043d\u043e\u0433\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446 \u0438 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":24168,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-32353","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0418\u043d\u0436\u0435\u043d\u0435\u0440 \u2014 \u0432 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0435 \u0441 \u043b\u0430\u0442\u044b\u043d\u0438 \u2014 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0435\u043d\u043d\u044b\u0439. \u0418\u043d\u0436\u0435\u043d\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0432\u0441\u0451. (\u0441) \u0420.\u0414\u0438\u0437\u0435\u043b\u044c. \u042d\u043f\u0438\u0433\u0440\u0430\u0444\u044b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/monitoring-proizvoditelnosti-zaprosov-postgresql-chast-1-reporting\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 PostgreSQL. \u0427\u0430\u0441\u0442\u044c 1 \u2014 \u0440\u0435\u043f\u043e\u0440\u0442\u0438\u043d\u0433 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0418\u043d\u0436\u0435\u043d\u0435\u0440 \u2014 \u0432 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0435 \u0441 \u043b\u0430\u0442\u044b\u043d\u0438 \u2014 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0435\u043d\u043d\u044b\u0439. \u0418\u043d\u0436\u0435\u043d\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0432\u0441\u0451. (\u0441) \u0420.\u0414\u0438\u0437\u0435\u043b\u044c. \u042d\u043f\u0438\u0433\u0440\u0430\u0444\u044b.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/monitoring-proizvoditelnosti-zaprosov-postgresql-chast-1-reporting\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:46:32+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:46:32+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Monitoreo del rendimiento de las consultas PostgreSQL. Parte 1 \u2014 informes | ProHoster","description":"Ingeniero \u2014 traducido del lat\u00edn \u2014 significa inspirado. Un ingeniero puede hacer cualquier cosa. (c) R.Diesel. Ep\u00edgrafes.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/monitoring-proizvoditelnosti-zaprosov-postgresql-chast-1-reporting","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 PostgreSQL. \u0427\u0430\u0441\u0442\u044c 1 \u2014 \u0440\u0435\u043f\u043e\u0440\u0442\u0438\u043d\u0433 | ProHoster","og:description":"\u0418\u043d\u0436\u0435\u043d\u0435\u0440 \u2014 \u0432 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u0435 \u0441 \u043b\u0430\u0442\u044b\u043d\u0438 \u2014 \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u0435\u043d\u043d\u044b\u0439. \u0418\u043d\u0436\u0435\u043d\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0432\u0441\u0451. (\u0441) \u0420.\u0414\u0438\u0437\u0435\u043b\u044c. \u042d\u043f\u0438\u0433\u0440\u0430\u0444\u044b.","og:url":"https:\/\/prohoster.info\/es\/blog\/administrirovanie\/monitoring-proizvoditelnosti-zaprosov-postgresql-chast-1-reporting","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:46:32+00:00","article:modified_time":"2019-10-31T18:46:32+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"32353","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 10:28:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 19:13:42","updated":"2026-01-21 10:28:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/32353","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=32353"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/32353\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/24168"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=32353"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=32353"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=32353"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}