Salut à toutes et tous, aujourd’hui un petit post pour évoquer les quelques petites modifications apportées à pg_stat_statements, l’extension phare de PostgreSQL, et qui ont pu passer inaperçues depuis le 13 octobre, date de sortie de la dernière release majeure du SGBD aux grandes oreilles.
Si vous n’êtes pas familiers de pg_stat_statements je vous renvoie sur mon talk aux PGDays en 2021.
Si on regarde d’un peu plus près la documentation de référence, on va retrouver deux ajouts principaux:
Séparation des stats IO data & temporary
Tout d’abord en version 14, les colonnes blk_read_time et blk_write_time comptabilisaient les entrées / sorties vers tous les blocs, à la fois data et temporary. En version 15, deux nouvelles colonnes temp_blk_read_time et temp_blk_write_time sont ajoutées à la vue, pour séparer les deux types d’accès. Les anciennes colonnes ne font donc plus référence qu’aux accès aux blocs de data, et les 2 nouvelles qu’aux accès aux blocs temporary.
Infos sur les compilations JIT:
La deuxième différence qui est nettement plus visible, est l’ajout de toute la métrologie associée à la compilation Jit, introduite en 2018 pour la version 11 par Andres Freund, et qui permet d’accélérer l’exécution de code PL/PGSQL davantage en le compilant en langage natif à l’exécution, si le coût dépasse un seuil fixé par le paramètre jit_above_cost. Parmi ces nouvelles colonnes :
jit_functions : Total number of functions JIT-compiled by the statement jit_generation_time : Total time spent by the statement on generating JIT code, in milliseconds jit_inlining_count : Number of times functions have been inlined jit_inlining_time : Total time spent by the statement on inlining functions, in milliseconds jit_optimization_count : Number of times the statement has been optimized jit_optimization_time : Total time spent by the statement on optimizing, in milliseconds jit_emission_count : Number of times code has been emitted jit_emission_time : Total time spent by the statement on emitting code, in milliseconds
Petit test pour voir avec une bonne grosse requête qui va nous faire un parallel seq scan et un hash aggregate en sortie, le tout sur 40 millions de lignes. Pour avoir un peu de volumétrie j’utilise la base de test de musicbrainz que je vous recommande:
(postgres@[local]:5432) [postgres] > select name, setting from pg_settings where name in ('jit','jit_above_cost') ; name | setting ----------------+--------- jit | on jit_above_cost | 100000 (2 rows) (postgres@[local]:5432) [postgres] > \c musicbrainz You are now connected to database "musicbrainz" as user "postgres". (postgres@[local]:5432) [musicbrainz] > explain select name, count(id), avg(length) from track group by name having count(id) > 5 ; QUERY PLAN --------------------------------------------------------------------------------------------------- Finalize GroupAggregate (cost=2399394.22..2481941.16 rows=104483 width=60) Group Key: name Filter: (count(id) > 5) -> Gather Merge (cost=2399394.22..2472537.66 rows=626900 width=60) Workers Planned: 2 -> Sort (cost=2398394.20..2399177.83 rows=313450 width=60) Sort Key: name -> Partial HashAggregate (cost=2124704.40..2357991.54 rows=313450 width=60) Group Key: name Planned Partitions: 16 -> Parallel Seq Scan on track (cost=0.00..741158.22 rows=16834022 width=28) JIT: Functions: 8 Options: Inlining true, Optimization true, Expressions true, Deforming true (14 rows)
OK on voit bien qu’avec notre cost final de +2399394 on est au dessus des 100K minimums nécessaire pour forcer le JIT. Exécutons la requête pour voir ce que l’on retrouve dans pg_stat_statements:
(postgres@[local]:5432) [musicbrainz] > select name, count(id), avg(length) from track group by name having count(id) > 5 ; (...) (746785 rows) Time: 210439.640 ms (03:30.440) (postgres@[local]:5432) [postgres] > \x Expanded display is on. (postgres@[local]:5432) [postgres] > select * from pg_stat_statements where query like 'select name, count(id), avg(length) from track%' ; -[ RECORD 1 ]----------+----------------------------------------------------------------------------------- userid | 10 dbid | 16388 toplevel | t queryid | 6022129428306982548 query | select name, count(id), avg(length) from track group by name having count(id) > $1 plans | 0 total_plan_time | 0 min_plan_time | 0 max_plan_time | 0 mean_plan_time | 0 stddev_plan_time | 0 calls | 1 total_exec_time | 210435.894037 min_exec_time | 210435.894037 max_exec_time | 210435.894037 mean_exec_time | 210435.894037 stddev_exec_time | 0 rows | 746785 shared_blks_hit | 16 shared_blks_read | 572818 shared_blks_dirtied | 0 shared_blks_written | 0 local_blks_hit | 0 local_blks_read | 0 local_blks_dirtied | 0 local_blks_written | 0 temp_blks_read | 1071638 temp_blks_written | 1325851 blk_read_time | 0 blk_write_time | 0 temp_blk_read_time | 0 temp_blk_write_time | 0 wal_records | 0 wal_fpi | 0 wal_bytes | 0 jit_functions | 15 jit_generation_time | 1.491564 jit_inlining_count | 1 jit_inlining_time | 237.918294 jit_optimization_count | 1 jit_optimization_time | 360.290152 jit_emission_count | 1 jit_emission_time | 230.831919
Le cost étant à 2M+ on aura donc à la fois inlining et optimization car les 2 seuils jit_inline_above_cost et jit_optimize_above_cost sont à 500K, ce qui est confirmé par la sortie de PGSS ci-dessus.
Pour ce qui est de la version 16, qui devrait être ouverte en Beta d’ici un ou deux mois, pour l’instant pas d’ajout de nouvelle colonne à l’horizon.
Pensez à vous abonner à la page linkedin et à la chaîne youtube de Capdata si ce n’est pas déjà fait !
A+
Continuez votre lecture sur le blog :
- Requêtes consommatrices sous PostgreSQL (épisode 1) (David Baffaleuf) [PostgreSQL]
- DMV et problème de tri (David Baffaleuf) [SQL Server]
- “Pruning” de partitions sous PostgreSQL ou comment bien élaguer ! (Capdata team) [PostgreSQL]
- PGDay Nantes 2021 session sur pg_stat_statements (David Baffaleuf) [PostgreSQL]
- AWS RDS : les extensions PostgreSQL (Emmanuel RAMI) [AWSPostgreSQL]