Nantes, le 25 novembre 2020
La vue pg_stat_activity
s’est vu ajouter un champ leader_pid
dans la
version 13 de PostgreSQL. Voici plus de détails sur les personnes à
l’origine de cette fonctionnalité, son fonctionnement et ses possibles
utilisations.
Lors de la session de questions et réponses qui suivait mon intervention au
sujet des nouveautés de la version 13 de PostgreSQL, j’ai dit que Dalibo avait
participé au développement du patch sur l’ajout de la colonne leader_pid
dans
la vue pg_stat_activity
. Cela mérite quelques précisions.
La fonctionnalité a été développée par Julien Rouhaud (VMware), et a été revue par Sergei Kornilov (Data Egret), Guillaume Lelarge (Dalibo), Michael Paquier (VMWare) et Tomas Vondra (2ndQuadrant). Le patch a été commité par Michael Paquier (VMWare). Vous pouvez retrouver plus d’informations sur les commits ici et là.
Voici une présentation rapide de cette nouveauté, qui permet depuis la vue
pg_stat_activity
, de faire simplement un lien entre le processus leader
d’une requête parallélisée et ses processus parallel worker.
La colonne leader_pid
contient le pid du processus leader pour chaque ligne
de pg_stat_activity
correspondant à un processus worker. Elle contient
NULL
dans tous les autres cas. Voici un exemple :
PG13> SELECT leader_pid AS lpid, pid, state, backend_type, query
FROM pg_stat_activity
WHERE backend_type IN ('client backend', 'parallel worker');
lpid | pid | state | backend_type | query
--------+--------+--------+-----------------+-----------------------------------------
NULL | 207706 | active | client backend | SELECT avg(i) FROM test_nonparallelise;
NULL | 207949 | active | client backend | SELECT avg(i) FROM test_parallelise;
NULL | 207959 | active | client backend | SELECT avg(i) FROM test_parallelise;
207959 | 208561 | active | parallel worker | SELECT avg(i) FROM test_parallelise;
207959 | 208562 | active | parallel worker | SELECT avg(i) FROM test_parallelise;
207949 | 208564 | active | parallel worker | SELECT avg(i) FROM test_parallelise;
207949 | 208565 | active | parallel worker | SELECT avg(i) FROM test_parallelise;
On peut observer que les backends 208561 et 208562 sont des parallel workers invoqués pour aider le backend 207959 à exécuter sa requête.
Dans les versions précédentes de PostgreSQL, il était difficile de rattacher un parallel worker à son processus leader.
Il y a eu plusieurs évolutions depuis la mise en place du parallélisme. En
version 9.6, les processus dédiés au parallélisme étaient visibles dans la vue
pg_stat_activity
, mais la plupart des informations n’étaient pas renseignées.
En version 10, les processus parallel worker étaient catégorisés comme
background worker
dans celle-ci. Depuis la version 11 de PostgreSQL, la
colonne backend_type
a une dénomination spécifique pour ces processus dédiés
à la parallélisation des requêtes : parallel worker
.
Ce petit historique illustre le processus d’amélioration continue des fonctionnalités de PostgreSQL.
Voici un exemple de ce que l’on peut voir avec PostgreSQL 12 :
PG12 > SELECT pid, state, backend_type, query
FROM pg_stat_activity
WHERE backend_type IN ('client backend', 'parallel worker');
pid | state | backend_type | query
--------+--------+-----------------+-----------------------------------------
206327 | active | client backend | SELECT avg(i) FROM test_parallelise;
206328 | active | client backend | SELECT avg(i) FROM test_parallelise;
206329 | active | client backend | SELECT avg(i) FROM test_nonparallelise;
207201 | active | parallel worker | SELECT avg(i) FROM test_parallelise;
207202 | active | parallel worker | SELECT avg(i) FROM test_parallelise;
207203 | active | parallel worker | SELECT avg(i) FROM test_parallelise;
207204 | active | parallel worker | SELECT avg(i) FROM test_parallelise;
Cette fonctionnalité est, de mon point de vue, très intéressante puisqu’elle va permettre de suivre l’utilisation du parallélisme plus simplement au niveau de l’instance.
Il sera notamment possible de compter le nombre de requêtes parallélisées, et le nombre de workers utilisés à un instant t :
PG13> SELECT COUNT(DISTINCT leader_pid) AS nb_requetes_parallelisees,
COUNT(leader_pid) AS parallel_workers
FROM pg_stat_activity
WHERE leader_pid IS NOT NULL
AND backend_type = 'parallel worker';
nb_requetes_parallelisees | parallel_workers
---------------------------+-----------------
2 | 4
Voici un autre exemple, qui permet de récupérer les processus parallel worker invoqués pour aider une session cliente à traiter un nœud d’exécution du plan d’une requête :
PG13> SELECT pid,
ARRAY(SELECT pid
FROM pg_stat_activity
WHERE leader_pid = psa.pid) AS workers,
state, query
FROM pg_stat_activity AS psa
WHERE backend_type = 'client backend';
pid | workers | state | query
--------+-----------------+--------+--------------------------------------
684097 | {684113,684114} | active | SELECT count(*) FROM test_parallelise;