PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 14.15 » Langage SQL » Requêtes parallélisées » Comment fonctionne la parallélisation des requêtes

15.1. Comment fonctionne la parallélisation des requêtes

Quand l'optimiseur détermine que la parallélisation est la stratégie la plus rapide pour une requête particulière, il crée un plan d'exécution incluant un nœud Gather ou un nœud Gather Merge. En voici un exemple simple :

EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
                                     QUERY PLAN
-------------------------------------------------------------------------------------
 Gather  (cost=1000.00..217018.43 rows=1 width=97)
   Workers Planned: 2
   ->  Parallel Seq Scan on pgbench_accounts  (cost=0.00..216018.33 rows=1 width=97)
         Filter: (filler ~~ '%x%'::text)
(4 rows)
   

Dans tous les cas, le nœud Gather ou Gather Merge aura exactement un nœud enfant, qui est la portion du plan exécutée en parallèle. Si le nœud Gather ou Gather Merge est à la racine du plan, alors la requête entière est parallélisée. S'il est placé ailleurs dans le plan, alors seule cette portion du plan s'exécutera en parallèle. Dans l'exemple ci-dessus, la requête accède à une seule table, donc il n'existe qu'un seul autre nœud de plan que le nœud Gather lui-même ; comme ce nœud est un enfant du nœud Gather, il s'exécutera en parallèle.

En utilisant EXPLAIN, vous pouvez voir le nombre de processus auxiliaires (appelés workers) choisis par le planificateur. Quand le nœud Gather est atteint lors de l'exécution de la requête, le processus en charge de la session demandera un nombre de processus d'arrière-plan (background workers) égal au nombre de workers choisi par le planificateur. Le nombre de background workers que le planificateur envisagera est limité à au plus la valeur de max_parallel_workers_per_gather. Le nombre total de background workers pouvant exister à un même moment est limité par les paramètres max_worker_processes et max_parallel_workers. De ce fait, il est possible qu'une requête parallélisée s'exécute avec moins de workers que prévu, voire sans worker du tout. Le plan optimal peut dépendre du nombre de workers disponibles, ce qui peut résulter en de médiocres performances des requêtes. Si cela survient fréquemment, envisagez l'augmentation de max_worker_processes et de max_parallel_workers pour qu'un plus grand nombre de workers puissent travailler simultanément ou la diminution de max_parallel_workers_per_gather pour que le planificateur réclame moins de workers.

Chaque processus background worker démarré avec succès dans une requête parallélisée donnée exécutera la portion parallélisée du plan. Le processus principal, appelé leader, exécutera aussi cette portion du plan bien qu'il ait des responsabilités supplémentaires : il doit aussi lire toutes les lignes générées par les workers. Quand la portion parallélisée du plan ne génère qu'un petit nombre de lignes, le leader se comportera souvent comme un worker supplémentaire, accélérant l'exécution de la requête. Par contre, quand la portion parallèle du plan génère un grand nombre de lignes, le leader peut être accaparé par la lecture des lignes générées par les workers et par le traitement des autres étapes au-dessus du nœud Gather ou du nœud Gather Merge. Dans de tels cas, le leader travaillera très peu sur la portion parallélisée du plan.

Quand le nœud principal de la portion parallélisée est Gather Merge au lieu de Gather, cela indique que chaque processus exécutant la portion parallélisée du plan produit des lignes triées, et que le processus principal s'occupe de conserver l'ordre des lignes pendant leur assemblage. Par contre, Gather lit les lignes de processus d'aide dans n'importe quel ordre, détruisant tout ordre qui aurait pu exister.