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 .

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;

DALIBO

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