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.

visuel annonce

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.

visuel annonce

À la fin de ces trois jours, nous nous retrouvons avec quatre patchs, et donc quatre threads lancés sur pgsql-hackers.

visuel annonce

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 :

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.


DALIBO

DALIBO est le spécialiste français de PostgreSQL®. Nous proposons du support, de la formation et du conseil depuis 2005.