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.