Reviers, le 16 septembre 2024
Dalibo participe au développement de PostgreSQL autant que possible. Avant, c’était plutôt chacun dans son coin, lors de sa semaine de R&D, mais cela ne permettait pas de s’attaquer à de gros projets. L’envie s’est fait donc ressentir de travailler à plusieurs sur un développement particulier. Et en voici un exemple.
La parallélisation dans PostgreSQL
La parallélisation est apparue dans PostgreSQL en 2016 avec la version 9.6. Les versions suivantes ont amélioré cette fonctionnalité en acceptant de paralléliser plus de nœuds d’exécution et en proposant plus de configuration. Cependant, il reste toujours compliqué de savoir si la parallélisation est utilisée et, si oui, à bon escient, pour les bonnes requêtes. En effet, actuellement, les deux seuls moyens de savoir si une requête est parallélisée sont de rechercher les processus parallel workers
(soit avec une commande systeme comme ps
ou top
, soit avec la vue système pg_stat_activity
), soit en récupérant son plan d’exécution (manuellement avec un EXPLAIN
ou automatiquement avec auto_explain
).
Il y a quelques années, Benoit Lobreau, un des consultants DBA de dalibo, avait commencé une réflexion à ce sujet. En 2022, il a envoyé deux mails sur la liste des développeurs de PostgreSQL, pgsql-hackers, un pour discuter de traces supplémentaires (« Logging parallel worker draught »), un autre pour discuter de statistiques additionnelles (« Parallel Query Stats »). Des discussions ont suivi, elles ont aussi un peu traîné, suite a l’indisponibilité des uns puis des autres. Et nous voici en 2024 avec la ferme intention de relancer le sujet, bien plus sérieusement, et en lui allouant du temps officiel.
Cowork à Nantes
De ce fait, Benoit Lobreau, Franck Boudehen, Jehan-Guillaume de Rorthais et moi-même venons de passer trois jours à Nantes pour nous focaliser entièrement sur ce thème de la supervision de la parallélisation dans PostgreSQL.
À la fin de ces trois jours, nous nous retrouvons avec quatre patchs, et donc quatre threads lancés sur pgsql-hackers.
Patch sur les traces
Le premier patch est une refonte du patch de Benoit sur les traces. Il accepte maintenant un paramètre de configuration, log_parallel_workers
qui se comporte sensiblement comme le paramètre log_temp_files
. Suivant sa configuration, il ajoute une ligne dans les traces chaque fois qu’une requête est parallélisée en indiquant le nombre de workers demandés par le planificateur, le nombre de workers rellement exécutés, ainsi que plusieurs autres métriques. Voici un exemple de cette trace :
LOG: 1 parallel nodes planned (1 obtained all their workers, 0 obtained none), 2 workers planned (2 workers launched)
Si ce patch est intégré, il sera alors intéressant de modifier pgbagder pour ajouter un rapport sur les traces de parallélisation.
Patchs sur les statistiques
Les trois autres patchs concernent les vues statistiques pg_stat_database
, pg_stat_all_tables
(et pg_stat_all_indexes
), et pg_stat_statements
.
La vue pg_stat_database
propose quatre nouvelles colonnes : parallel_worker_planned
, parallel_worker_launched
, parallel_maint_worker_planned
, et parallel_maint_worker_launched
. Il est ainsi possible de connaître, respectivement, le nombre de workers
planifiés et exécutés, pour les opérations standards et pour les opérations de maintenance. Voici un exemple de la vue :
SELECT datname,
parallel_workers_planned, parallel_workers_launched,
parallel_maint_workers_planned, parallel_maint_workers_launched
FROM pg_stat_database
WHERE datname = 'postgres' \gx
-[ RECORD 1 ]-------------------+---------
datname | postgres
parallel_workers_planned | 6
parallel_workers_launched | 3
parallel_maint_workers_planned | 7
parallel_maint_workers_launched | 4
Les vues pg_stat_all_tables
et pg_stat_all_indexes
gagnent respectivement 4 et 2 colonnes. Voici un exemple de pg_stat_all_tables
:
SELECT relname, seq_scan, last_seq_scan, parallel_seq_scan, last_parallel_seq_scan
FROM pg_stat_user_tables
WHERE relname='t1' \gx
-[ RECORD 1 ]----------+------------------------------
relname | t1
seq_scan | 4
last_seq_scan | 2024-08-29 15:43:18.504533+02
parallel_seq_scan | 3
last_parallel_seq_scan | 2024-08-29 15:43:18.504533+02
Et enfin la vue pg_stat_statements
gagne sept colonnes :
SELECT query,
parallelized_queries_planned, parallelized_queries_launched,
parallelized_workers_planned, parallelized_workers_launched,
parallelized_nodes, parallelized_nodes_all_workers, parallelized_nodes_no_worker
FROM pg_stat_statements
WHERE query LIKE 'SELECT%t1%'
-[ RECORD 1 ]------------------+--------------------------
query | SELECT count(*) FROM t1
parallelized_queries_planned | 2
parallelized_queries_launched | 2
parallelized_workers_planned | 6
parallelized_workers_launched | 6
parallelized_nodes | 2
parallelized_nodes_all_workers | 2
parallelized_nodes_no_worker | 0
-[ RECORD 2 ]------------------+--------------------------
query | SELECT * FROM t1 LIMIT $1
parallelized_queries_planned | 0
parallelized_queries_launched | 0
parallelized_workers_planned | 0
parallelized_workers_launched | 0
parallelized_nodes | 0
parallelized_nodes_all_workers | 0
parallelized_nodes_no_worker | 0
Vous trouverez plus de détails et d’exemples sur les threads associés :
- Logging parallel worker draught
- Parallel workers stats in pg_stat_database
- Add parallel columns for seq scan and index scan on pg_stat_all_tables and _indexes
- Add parallel columns for pg_stat_statements
Et la suite ?
Les mails ont été envoyés fin août, il est encore bien trop tôt pour dire s’ils seront acceptés sous cette forme (peu probable) ou sous une forme améliorée (plus probable), voire rejetés (c’est un risque). Nous vous tiendrons évidemment au courant. Ceci étant dit, l’expérience est une réussite, de l’avis de tous les participants et l’envie de recommencer est déjà là. Reste à trouver le prochain sujet à investiguer.