{"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\/fr\/blog\/administrirovanie\/monitoring-proizvoditelnosti-zaprosov-postgresql-chast-1-reporting","title":{"rendered":"Surveillance des performances des requ\u00eates PostgreSQL. Partie 1 \u2014 rapport","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ing\u00e9nieur \u2014 du latin, cela signifie inspir\u00e9.<br \/>\nL'ing\u00e9nieur peut tout faire. (c) R.Diesel.<br \/>\n<i>\u00c9pigraphes.<\/i><br \/>\n<img decoding=\"async\" alt=\"Surveillance des performances des requ\u00eates PostgreSQL. Partie 1 \u2014 rapport\" src=\"\/wp-content\/uploads\/2019\/04\/9a2640267ea05006b94e03642b864ddc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ou l'histoire de la raison pour laquelle un administrateur de base de donn\u00e9es devrait se souvenir de son pass\u00e9 de programmeur. <\/i><\/p>\n<h2>Pr\u00e9face<\/h2>\n<p>\nTous les noms ont \u00e9t\u00e9 modifi\u00e9s. Les co\u00efncidences sont fortuites. Le mat\u00e9riel repr\u00e9sente uniquement l'opinion personnelle de l'auteur.<\/p>\n<blockquote><p><b>Avertissement sur les garanties :<\/b> <i>Il n'y aura pas de description d\u00e9taill\u00e9e et pr\u00e9cise des tables et scripts utilis\u00e9s dans le cycle d'articles pr\u00e9vu. Les mat\u00e9riaux ne pourront pas \u00eatre utilis\u00e9s imm\u00e9diatement 'EN L'\u00c9TAT'. <br \/>\nTout d'abord, en raison du volume important de mat\u00e9riel, <br \/>\ndeuxi\u00e8mement, en raison de l'ad\u00e9quation avec la base de production du client r\u00e9el. <br \/>\nC'est pourquoi les articles ne pr\u00e9senteront que des id\u00e9es et des descriptions de mani\u00e8re tr\u00e8s g\u00e9n\u00e9rale. <br \/>\nPeut-\u00eatre qu'\u00e0 l'avenir, le syst\u00e8me \u00e9voluera vers le partage sur GitHub, ou peut-\u00eatre pas. Le temps le dira.<\/i><\/p><\/blockquote>\n<p>\nD\u00e9but de l'histoire - \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/icl_services\/blog\/446314\/\">Tu te souviens comment tout a commenc\u00e9 ?<\/a><\/noindex>\u00bb.<br \/>\nCe qui en est sorti, en termes tr\u00e8s g\u00e9n\u00e9raux - \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/444988\/\">La synth\u00e8se comme l'une des m\u00e9thodes d'am\u00e9lioration de la performance de PostgreSQL<\/a><\/noindex>\u00bb<\/p>\n<h2>Pourquoi tout cela m'int\u00e9resse-t-il ?<\/h2>\n<p>\nEh bien, d'abord pour ne pas oublier, en me rappelant les bons jours \u00e0 la retraite. <br \/>\nDeuxi\u00e8mement, pour syst\u00e9matiser ce qui a \u00e9t\u00e9 \u00e9crit. Car parfois, je commence moi-m\u00eame \u00e0 me perdre et \u00e0 oublier certaines parties. <\/p>\n<p>Et surtout, qui sait, cela pourrait \u00eatre utile \u00e0 quelqu'un et l'aider \u00e0 ne pas r\u00e9inventer la roue ou \u00e0 ne pas se manger les doigts. En d'autres termes, am\u00e9liorer son karma (pas au sens Habr). Car, ce qui est le plus pr\u00e9cieux dans ce monde, ce sont les id\u00e9es. L'essentiel est de trouver une id\u00e9e. La concr\u00e9tiser est une question purement technique.<\/p>\n<p>Alors, commen\u00e7ons doucement\u2026<\/p>\n<h2>\u00c9nonc\u00e9 du probl\u00e8me.<\/h2>\n<p><\/p>\n<h3>Il y a : <\/h3>\n<p>\nBase de donn\u00e9es PostgreSQL (10.5), de type de charge mixte (OLTP+DSS), de charge moyenne \u00e0 faible, situ\u00e9e dans le cloud AWS. <br \/>\nLa surveillance de la base de donn\u00e9es est absente, la surveillance de l'infrastructure est assur\u00e9e par les outils standards d'AWS dans une configuration minimale.<\/p>\n<h3>Exigences :<\/h3>\n<p>\nSurveiller les performances et l'\u00e9tat de la base de donn\u00e9es, trouver et disposer d'informations initiales pour optimiser les requ\u00eates lourdes \u00e0 la base de donn\u00e9es.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Introduction ou analyse des options de solution<\/h2>\n<p>\nPour commencer, essayons d'examiner les options de solution du point de vue d'une analyse comparative des avantages et des d\u00e9sagr\u00e9ments pour l'ing\u00e9nieur, tandis que les b\u00e9n\u00e9fices et les pertes pour la direction peuvent \u00eatre trait\u00e9s par ceux qui sont responsables selon l'organigramme.<\/p>\n<h3>Option 1 - \u00abTravailler \u00e0 la demande\u00bb<\/h3>\n<p>\nNous laissons tout comme c'est. Si le client n'est pas satisfait de la performance de la base de donn\u00e9es ou de l'application, il informera les ing\u00e9nieurs DBA par e-mail ou en cr\u00e9ant un incident dans le syst\u00e8me de tickets. <br \/>\nL'ing\u00e9nieur, apr\u00e8s avoir re\u00e7u l'alerte, se penchera sur le probl\u00e8me, proposera une solution ou reportera le probl\u00e8me, esp\u00e9rant que tout se r\u00e9soudra de lui-m\u00eame, et de toute fa\u00e7on, tout sera bient\u00f4t oubli\u00e9.<br \/>\n<b class=\"spoiler_title\">G\u00e2teaux et beignets, bleus et bosses<\/b><b>G\u00e2teaux et beignets :<\/b><br \/>\n1. Il n'est pas n\u00e9cessaire de faire quoi que ce soit de superflu.<br \/>\n2. Il y a toujours la possibilit\u00e9 de se d\u00e9filer et de feinter. <br \/>\n3. Une montagne de temps que l'on peut utiliser \u00e0 sa guise.<br \/>\n<b>Bleus et bosses :<\/b><br \/>\n1. T\u00f4t ou tard, le client se posera des questions sur la nature de l'existence et la justice universelle dans ce monde, et se demandera encore : pourquoi paye-t-il de l'argent ? Les cons\u00e9quences sont toujours les m\u00eames \u2014 la seule question est quand le client s'ennuiera et se r\u00e9signera \u00e0 dire au revoir. Et le gagne-pain se videra. C'est triste.<br \/>\n2. Le d\u00e9veloppement de l'ing\u00e9nieur \u2014 z\u00e9ro.<br \/>\n3. Difficult\u00e9s dans la planification du travail et de la charge. <\/p>\n<h3>Option 2 - \u00abOn danse avec des tambourins, on vend et on chausse.\u00bb<\/h3>\n<p>\n<b>Point 1<\/b>-Pourquoi avons-nous besoin d'un syst\u00e8me de surveillance, nous traiterons toutes les demandes. Nous ex\u00e9cutons une multitude de demandes vers le dictionnaire de donn\u00e9es et les vues dynamiques, activons divers compteurs, compilons tout dans des tableaux, et analysons p\u00e9riodiquement les listes et tableaux. En fin de compte, nous avons de beaux graphiques ou pas tr\u00e8s beaux, des tableaux, des rapports. L'essentiel est d'avoir toujours plus.<br \/>\n<b>Point 2<\/b>-Nous g\u00e9n\u00e9rons de l'activit\u00e9 \u2014 nous lan\u00e7ons l'analyse de tout cela.<br \/>\n<b>Point 3<\/b>-Nous pr\u00e9parons un document, que nous appelons simplement \u2014 \u00abcomment organiser notre base de donn\u00e9es\u00bb.<br \/>\n<b>Point 4<\/b>-Le client, voyant toute cette magnificence de graphiques et de chiffres, est dans une na\u00efve confiance enfantine \u2014 voil\u00e0, maintenant tout va fonctionner, bient\u00f4t. Et il se s\u00e9pare facilement et sans douleur de ses ressources financi\u00e8res. La direction est aussi convaincue \u2014 nos ing\u00e9nieurs travaillent d'arrache-pied. La charge est \u00e0 son maximum. <br \/>\n<b>Point 5<\/b>-R\u00e9p\u00e9ter r\u00e9guli\u00e8rement le Point 1.<br \/>\n<b class=\"spoiler_title\">G\u00e2teaux et beignets, bleus et bosses<\/b><b>G\u00e2teaux et beignets : <\/b><br \/>\n1. La vie des managers et des ing\u00e9nieurs est simple, pr\u00e9visible et pleine d'activit\u00e9. Tout bourdonne, tout le monde est occup\u00e9. <br \/>\n2. La vie du client n'est pas mal non plus \u2014 il est toujours s\u00fbr qu'il suffit de patienter un peu et tout se mettra en place. \u00c7a ne s'arrange pas, eh bien, que faire \u2014 c'est un monde injuste, peut-\u00eatre dans une prochaine vie \u2014 il aura de la chance.<br \/>\n<b>Bleus et bosses :<\/b><br \/>\n1. T\u00f4t ou tard, il y aura un fournisseur plus rapide offrant un service similaire, qui fera la m\u00eame chose, mais \u00e0 un prix l\u00e9g\u00e8rement inf\u00e9rieur. Et si le r\u00e9sultat est le m\u00eame, pourquoi payer plus ? Ce qui, encore une fois, entra\u00eenera la disparition de cette source de revenus.<br \/>\n2. C'est ennuyeux. Tout aussi ennuyeux que n'importe quelle activit\u00e9 peu significative.<br \/>\n3. Comme dans l'option pr\u00e9c\u00e9dente, il n'y a pas de d\u00e9veloppement. Mais pour un ing\u00e9nieur, un inconv\u00e9nient est que, contrairement \u00e0 la premi\u00e8re option, ici il faut constamment g\u00e9n\u00e9rer des bases de donn\u00e9es d'informations. Et cela prend du temps. Un temps qui pourrait \u00eatre utilis\u00e9 de mani\u00e8re b\u00e9n\u00e9fique pour soi-m\u00eame. Car si on ne prend pas soin de soi, personne ne le fera.<\/p>\n<h3>Option 3 - Il n'est pas n\u00e9cessaire de r\u00e9inventer la roue, il faut l'acheter et rouler.<\/h3>\n<p>\nLes ing\u00e9nieurs d'autres entreprises ne mangent pas de pizza en buvant de la bi\u00e8re pour rien (ah, les bons vieux temps de Saint-P\u00e9tersbourg des ann\u00e9es 90). Utilisons des syst\u00e8mes de surveillance qui sont d\u00e9j\u00e0 con\u00e7us, test\u00e9s et fonctionnent, et qui apportent en fait un b\u00e9n\u00e9fice (au moins \u00e0 leurs cr\u00e9ateurs).<br \/>\n<b class=\"spoiler_title\">G\u00e2teaux et beignets, bleus et bosses<\/b><b>G\u00e2teaux et beignets :<\/b><br \/>\n1. Il n'est pas n\u00e9cessaire de perdre du temps \u00e0 cr\u00e9er ce qui a d\u00e9j\u00e0 \u00e9t\u00e9 cr\u00e9\u00e9. Prenez et utilisez.<br \/>\n2. Les syst\u00e8mes de surveillance ne sont pas con\u00e7us par des idiots et ils sont bien s\u00fbr utiles.<br \/>\n3. Les syst\u00e8mes de surveillance fonctionnels fournissent g\u00e9n\u00e9ralement des informations filtr\u00e9es pertinentes. <br \/>\n<b>Bleus et bosses :<\/b><br \/>\n1. Dans ce cas particulier, l'ing\u00e9nieur n'est pas un ing\u00e9nieur, mais simplement un utilisateur d'un produit d'autrui. Ou un utilisateur.<br \/>\n2. Il faut convaincre le client de la n\u00e9cessit\u00e9 d'acheter quelque chose qu'il ne veut, en r\u00e9alit\u00e9, pas comprendre ni devoir ; et en plus, le budget annuel a \u00e9t\u00e9 approuv\u00e9 et ne changera pas. Ensuite, il faut allouer des ressources distinctes et configurer pour un syst\u00e8me particulier. Donc, d'abord il faut payer, payer et encore payer. Et le client est avare. C'est la norme de cette vie.<\/p>\n<h2>Que faire - Tchernychevski ? Ta question est tout \u00e0 fait pertinente. (c)<\/h2>\n<p>\nDans ce cas pr\u00e9cis et la situation actuelle, on peut agir un peu diff\u00e9remment \u2014 <b>et pourquoi ne pas cr\u00e9er notre propre syst\u00e8me de surveillance. <\/b><br \/>\n<img decoding=\"async\" alt=\"Surveillance des performances des requ\u00eates PostgreSQL. Partie 1 \u2014 rapport\" src=\"\/wp-content\/uploads\/2019\/04\/b59a3ad9e16b68c0fbc962a61d571c52.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nEh bien, pas vraiment un syst\u00e8me au sens plein du terme, c'est trop ambitieux et pr\u00e9somptueux, mais au moins simplifier la t\u00e2che et recueillir plus d'informations pour r\u00e9soudre les incidents de performance. Afin de ne pas se retrouver dans une situation o\u00f9 il faut dire : \u00ab Va l\u00e0 o\u00f9 je ne sais pas o\u00f9, trouve ce que je ne sais pas quoi \u00bb.<\/p>\n<h4>Quels sont les avantages et les inconv\u00e9nients de cette option :<\/h4>\n<p><b>Avantages :<\/b><br \/>\n1. C'est int\u00e9ressant. Enfin, au moins plus int\u00e9ressant que les incessantes \u00ab shrink datafile, alter tablespace, etc. \u00bb <br \/>\n2. Ce sont de nouvelles comp\u00e9tences et un nouveau d\u00e9veloppement. Cela donnera t\u00f4t ou tard des r\u00e9compenses bien m\u00e9rit\u00e9es.<br \/>\n<b>Inconv\u00e9nients :<\/b><br \/>\n1. Il faudra travailler. Travailler beaucoup. <br \/>\n2. Il faudra r\u00e9guli\u00e8rement expliquer le sens et les perspectives de toute l'activit\u00e9.<br \/>\n3. Il faudra c\u00e9der \u00e0 quelque chose, car la seule ressource dont dispose l'ing\u00e9nieur \u2014 le temps \u2014 est limit\u00e9e par l'univers. <br \/>\n<b>4. Ce qui est le plus terrible et le plus d\u00e9sagr\u00e9able<\/b> \u2014 c'est qu'on peut finir par obtenir quelque chose comme \u00ab Ni souriceau, ni grenouille, mais une b\u00eate inconnue \u00bb.<\/p>\n<p><b>Qui ne risque rien n'a rien.<\/b><br \/>\nAlors \u2014 le plus int\u00e9ressant commence.<\/p>\n<h2>L'id\u00e9e g\u00e9n\u00e9rale \u2014 sch\u00e9matiquement<\/h2>\n<p>\n<img decoding=\"async\" alt=\"Surveillance des performances des requ\u00eates PostgreSQL. Partie 1 \u2014 rapport\" src=\"\/wp-content\/uploads\/2019\/04\/d1ae2ddc1d4c43353fe93eebdaa8b81a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n(<i>L'illustration est tir\u00e9e de l'article<\/i> \u00ab<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/444988\/\">La synth\u00e8se comme l'une des m\u00e9thodes d'am\u00e9lioration de la performance de PostgreSQL<\/a><\/noindex>\u00bb)<\/p>\n<p>Explication :<\/p>\n<ul>\n<li> Dans la base cible, l'extension standard PostgreSQL \u2014 \u00ab pg_stat_statements \u00bb \u2014 est install\u00e9e. <\/li>\n<li>Dans la base de donn\u00e9es de surveillance, nous cr\u00e9ons un ensemble de tables de service pour stocker l'historique de pg_stat_statements \u00e0 ses d\u00e9buts et pour configurer les m\u00e9triques et la surveillance par la suite.<\/li>\n<li> Sur l'h\u00f4te de surveillance, nous cr\u00e9ons un ensemble de scripts bash, y compris pour g\u00e9n\u00e9rer des incidents dans le syst\u00e8me de tickets. <\/li>\n<\/ul>\n<h2>Tables de service<\/h2>\n<p>\nPour commencer, voici un ERD sch\u00e9matique simplifi\u00e9 de ce qui a \u00e9t\u00e9 r\u00e9alis\u00e9 :<br \/>\n<img decoding=\"async\" alt=\"Surveillance des performances des requ\u00eates PostgreSQL. Partie 1 \u2014 rapport\" src=\"\/wp-content\/uploads\/2019\/04\/03d29f4d6932d470d9d88651cbf0c715.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<b class=\"spoiler_title\">Description succincte des tables<\/b><b>endpoint <\/b> \u2014 h\u00f4te, point de connexion \u00e0 l'instance<br \/>\n<b>database <\/b> \u2014 param\u00e8tres de la base de donn\u00e9es<br \/>\n<b>pg_stat_history <\/b> \u2014 table historique pour stocker des instantan\u00e9s temporels de la vue pg_stat_statements de la base de donn\u00e9es cible<br \/>\n<b>metric_glossary <\/b> \u2014 glossaire des m\u00e9triques de performance<br \/>\n<b>metric_config <\/b> \u2014 configuration des m\u00e9triques individuelles<br \/>\n<b>metric <\/b> \u2014 m\u00e9trique sp\u00e9cifique pour la requ\u00eate surveill\u00e9e<br \/>\n<b>metric_alert_history <\/b> \u2014 historique des alertes de performance<br \/>\n<b>log_query <\/b> \u2014 table de service pour stocker les enregistrements analys\u00e9s du fichier journal PostgreSQL charg\u00e9 depuis AWS<br \/>\n<b>baseline <\/b> \u2014 param\u00e8tres de la p\u00e9riode temporelle utilis\u00e9e comme r\u00e9f\u00e9rence <br \/>\n<b>checkpoint <\/b> \u2014 configuration des m\u00e9triques de v\u00e9rification de l'\u00e9tat de la base de donn\u00e9es<br \/>\n<b>checkpoint_alert_history <\/b> \u2014 historique des alertes des m\u00e9triques de v\u00e9rification de l'\u00e9tat de la base de donn\u00e9es<br \/>\n<b>pg_stat_db_queries <\/b> \u2014 table de service des requ\u00eates actives <br \/>\n<b>activity_log <\/b> \u2014 table de service du journal d'activit\u00e9 <br \/>\n<b>trap_oid <\/b> \u2014 table de service de configuration du trap<\/p>\n<p><\/p>\n<h2>\u00c9tape 1 \u2014 nous collectons des informations statistiques sur la performance et obtenons des rapports<\/h2>\n<p>\nLa table est utilis\u00e9e pour stocker les informations statistiques <b>pg_stat_history<\/b><br \/>\n<b class=\"spoiler_title\">Structure de la table pg_stat_history<\/b><\/p>\n<pre>\n                                          Table \"public.pg_stat_history\"\n       Column        |            Type             |                          Modifiers\n---------------------+-----------------------------+-------------------------------------------\n id                  | integer                     | not null default nextval('pg_stat_history_id_seq'::regclass)\n snapshot_timestamp  | timestamp without time zone |\n database_id         | integer                     |\n dbid                | oid                         |\n userid              | oid                         |\n queryid             | bigint                      |\n query               | text                        |\n calls               | bigint                      |\n total_time          | double precision            |\n min_time            | double precision            |\n max_time            | double precision            |\n mean_time           | double precision            |\n stddev_time         | double precision            |\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       | double precision            |\n blk_write_time      | double precision            |\n baseline_id         | integer                     |\nIndexes:\n    \"pg_stat_history_pkey\" PRIMARY KEY, btree (id)\n    \"database_idx\" btree (database_id)\n    \"queryid_idx\" btree (queryid)\n    \"snapshot_timestamp_idx\" btree (snapshot_timestamp)\nForeign-key constraints:\n    \"database_id_fk\" FOREIGN KEY (database_id) REFERENCES database(id) ON DELETE CASCADE<\/pre>\n<p>\nComme on peut le voir, la table repr\u00e9sente simplement des donn\u00e9es cumulatives de la vue <b>pg_stat_statements <\/b> dans la base de donn\u00e9es cible.<\/p>\n<h3>L'utilisation de cette table est tr\u00e8s simple<\/h3>\n<p>\n<b>pg_stat_history<\/b> repr\u00e9sentera des statistiques cumul\u00e9es sur l'ex\u00e9cution des requ\u00eates pour chaque heure. Au d\u00e9but de chaque heure, apr\u00e8s le remplissage de la table, les statistiques <b>pg_stat_statements<\/b> sont r\u00e9initialis\u00e9es \u00e0 l'aide de <b>pg_stat_statements_reset()<\/b>.<br \/>\nRemarque : <i>les statistiques sont collect\u00e9es pour les requ\u00eates ayant une dur\u00e9e d'ex\u00e9cution sup\u00e9rieure \u00e0 1 seconde.<\/i><br \/>\n<b class=\"spoiler_title\">Remplissage de la table 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 'NOUVEAU DOSSIER EN COURS DE CR\u00c9ATION';\n\t\t\n\t\t--Se connecter \u00e0 la base de donn\u00e9es cible\t  \n\t    EXECUTE 'SELECT dblink_connect(''LINK1'',''host='||endpoint_rec.host||' dbname='||database_rec.name||' user=USER password=PASSWORD '')';\n \n        RAISE NOTICE 'h\u00f4te % et dbname % ',endpoint_rec.host,database_rec.name;\n\t\tRAISE NOTICE 'Cr\u00e9ation d\u2019un instantan\u00e9 de pg_stat_statements pour la base de donn\u00e9es %',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 'Cr\u00e9ation d\u2019un instantan\u00e9 de pg_stat_statements pour les requ\u00eates ayant un temps minimum sup\u00e9rieur \u00e0 1000ms';\n\t\n        FOR pg_stat_snapshot IN\n          --Toutes les requ\u00eates avec un temps_max sup\u00e9rieur \u00e0 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>En cons\u00e9quence, apr\u00e8s un certain laps de temps dans le tableau <b>pg_stat_history<\/b> nous aurons un ensemble de captures du contenu du tableau <b>pg_stat_statements <\/b>de la base de donn\u00e9es cible. <\/p>\n<h2>En fait, le reporting<\/h2>\n<p>\nEn utilisant des requ\u00eates simples, on peut obtenir des rapports assez utiles et int\u00e9ressants.<\/p>\n<h2>Donn\u00e9es agr\u00e9g\u00e9es sur une p\u00e9riode donn\u00e9e<\/h2>\n<p><b class=\"spoiler_title\">Requ\u00eate<\/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>Temps 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>Temps 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 par total_time<\/h3>\n<p><b class=\"spoiler_title\">Requ\u00eate<\/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 PAR TEMPS D'EX\u00c9CUTION TOTAL\n|   #|    queryid|      appels|    % des appels|                total_time (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 par temps I\/O total<\/h4>\n<p><b class=\"spoiler_title\">Requ\u00eate<\/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 PAR TEMPS I\/O TOTAL\n|   #|    identifiant de requ\u00eate|      appels|    % d'appels|                   temps I\/O (ms)|% temps I\/O db\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 par le temps d'ex\u00e9cution maximum<\/h4>\n<p><b class=\"spoiler_title\">Requ\u00eate<\/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 PAR TEMPS D'EX\u00c9CUTION MAXIMAL\n|   #|          instantan\u00e9| identifiant de l'instantan\u00e9|    identifiant de requ\u00eate|                           temps_max (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 par la lecture\/\u00e9criture de tampon PARTAG\u00c9<\/h4>\n<p><b class=\"spoiler_title\">Requ\u00eate<\/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 PAR LECTURE\/\u00c9CRITURE DU BUFFER PARTAG\u00c9\n|   #|          instantan\u00e9| snapshotID|    queryid|   blocs partag\u00e9s lus|  blocs partag\u00e9s \u00e9crits\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>Histogramme de la r\u00e9partition des requ\u00eates par temps d'ex\u00e9cution maximal<\/h4>\n<p><b class=\"spoiler_title\">Requ\u00eates<\/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| HISTOGRAMME DU TEMPS MAXIMAL\n| APPELS TOTAUX : 33851920\n| TEMPS MIN  : 00:00:01.063\n| TEMPS MAX  : 00:02:01.869\n---------------------------------------------------------------------------------\n|                      dur\u00e9e min|                      dur\u00e9e max|     appels\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 Instantan\u00e9s par Requ\u00eate par Seconde<\/h4>\n<p><b class=\"spoiler_title\">Requ\u00eates<\/b><\/p>\n<pre><code class=\"plaintext\">--pg_qps.sql\n--Calculer le nombre de requ\u00eates par seconde \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 'ERREUR - pg_stat_history non trouv\u00e9 pour 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 Snapshots class\u00e9s par le nombre de QueryPerSeconds\n-----------------------------------------------------------------------------------------------------------------------------------------------\n|    #|          snapshot| snapshotID|      appels|                      temps total db|        QPS|                          temps I\/O| Pourcentage temps 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>Historique d'ex\u00e9cution horaire avec QueryPerSeconds et Temps I\/O<\/h4>\n<p><b class=\"spoiler_title\">Requ\u00eate<\/b><\/p>\n<pre><code class=\"plaintext\">SELECT \n  id , \n  snapshot_timestamp ,\n  appels , \t\n  temps_total , \n  ( select pg_qps( id )) AS QPS ,\n  temps_blk_lecture ,\n  temps_blk_ecriture\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| HISTORIQUE D'EX\u00c9CUTION HORAIRE AVEC QueryPerSeconds et Temps I\/O\n-----------------------------------------------------------------------------------------------------------------------------------------------\n| HISTORIQUE DES REQU\u00caTES PAR SECONDE\n|    #|          instantan\u00e9| snapshotID|      appels|                      temps total db|        QPS|                          temps I\/O| % temps 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>Texte de tous les SQL-selects<\/h4>\n<p><b class=\"spoiler_title\">Requ\u00eate<\/b><\/p>\n<pre><code class=\"plaintext\">SELECT \n  queryid , \n  query \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 , query\n<\/code><\/pre>\n<h2>Conclusion<\/h2>\n<p>\nComme on peut le voir, avec des moyens assez simples, il est possible d'obtenir beaucoup d'informations utiles sur la charge et l'\u00e9tat de la base de donn\u00e9es. <\/p>\n<p><b>Remarque :<\/b>Si nous enregistrons le queryid dans les requ\u00eates, nous obtiendrons un historique pour chaque requ\u00eate (dans un souci d'\u00e9conomie d'espace, les rapports pour chaque requ\u00eate sont omis).<\/p>\n<p>Ainsi, les donn\u00e9es statistiques sur les performances des requ\u00eates sont disponibles et collect\u00e9es.<br \/>\nLa premi\u00e8re \u00e9tape, \u00ab collecte de donn\u00e9es statistiques \u00bb, est termin\u00e9e.<\/p>\n<p>Nous pouvons passer \u00e0 la deuxi\u00e8me \u00e9tape : \u00ab configuration des m\u00e9triques de performance \u00bb.<br \/>\n<img decoding=\"async\" alt=\"Surveillance des performances des requ\u00eates PostgreSQL. Partie 1 \u2014 rapport\" src=\"\/wp-content\/uploads\/2019\/04\/a893e49280d4cb425e4667a5c51d2397.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b>Mais c'est d\u00e9j\u00e0 une toute autre histoire.<\/b><\/p>\n<p><i>\u00c0 suivre...<\/i><br \/>\n<br \/>Source : <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\/fr\/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=\"fr_FR\" \/>\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\/fr\/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\udd47Surveillance des performances des requ\u00eates PostgreSQL. Partie 1 \u2014 reporting | ProHoster","description":"Ing\u00e9nieur \u2014 traduit du latin \u2014 inspir\u00e9. L'ing\u00e9nieur peut tout faire. (c) R.Diesel. \u00c9pigraphes.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/administrirovanie\/monitoring-proizvoditelnosti-zaprosov-postgresql-chast-1-reporting","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","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\/fr\/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\/fr\/wp-json\/wp\/v2\/posts\/32353","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=32353"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/32353\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/24168"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=32353"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=32353"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=32353"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}