15.1. Cómo funcionan las consultas en paralelo #

Cuando el optimizador determina que las consultas en paralelo son la estrategia de ejecución más rápida para una consulta en particular, creará un plan de consulta que incluye un nodo Gather o Gather Merge. Aquí tienes un ejemplo sencillo:

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)

En todos los casos, el nodo Gather o Gather Merge tendrá exactamente un plan hijo (child plan), que es la parte del plan que se ejecutará en paralelo. Si el nodo Gather o Gather Merge está en la parte más alta del árbol de planificación, toda la consulta se ejecutará en paralelo. Si está en algún otro lugar del árbol, solo la porción del plan por debajo de él se ejecutará en paralelo. En el ejemplo anterior, la consulta accede solo a una tabla, por lo que solo hay un nodo de plan aparte del propio nodo Gather; dado que ese nodo de plan es hijo del nodo Gather, se ejecutará en paralelo.

Usando EXPLAIN, puedes ver el número de trabajadores (workers) elegidos por el planificador. Cuando se alcanza el nodo Gather durante la ejecución de la consulta, el proceso que implementa la sesión del usuario solicitará un número de procesos trabajadores en segundo plano (background workers) igual al número de trabajadores elegido por el planificador. El número de trabajadores en segundo plano que el planificador considerará usar está limitado a como máximo max_parallel_workers_per_gather. El número total de trabajadores en segundo plano que pueden existir simultáneamente está limitado tanto por max_worker_processes como por max_parallel_workers. Por lo tanto, es posible que una consulta en paralelo se ejecute con menos trabajadores de los planificados, o incluso sin ningún trabajador. El plan óptimo puede depender del número de trabajadores disponibles, por lo que esto puede resultar en un bajo rendimiento de la consulta. Si esto ocurre con frecuencia, considera aumentar max_worker_processes y max_parallel_workers para que se puedan ejecutar más trabajadores de forma simultánea, o bien reducir max_parallel_workers_per_gather para que el planificador solicite menos trabajadores.

Cada proceso trabajador en segundo plano que se inicia con éxito para una consulta en paralelo dada ejecutará la parte paralela del plan. El líder también ejecutará esa parte del plan, pero tiene una responsabilidad adicional: también debe leer todas las tuplas generadas por los trabajadores. Cuando la porción paralela del plan genera solo un número pequeño de tuplas, el líder a menudo se comportará de manera muy similar a un trabajador adicional, acelerando la ejecución de la consulta. Por el contrario, cuando la porción paralela del plan genera una gran cantidad de tuplas, el líder puede estar ocupado casi por completo leyendo las tuplas generadas por los trabajadores y realizando los pasos de procesamiento adicionales requeridos por los nodos del plan por encima del nivel del nodo Gather o del nodo Gather Merge. En tales casos, el líder hará muy poco trabajo de la ejecución de la porción paralela del plan.

Cuando el nodo en la parte superior de la porción paralela del plan es Gather Merge en lugar de Gather, indica que cada proceso que ejecuta la porción paralela del plan está produciendo tuplas en orden ordenado, y que el líder está realizando una fusión que preserva el orden. Por el contrario, Gather lee las tuplas de los trabajadores en el orden que le resulte conveniente, destruyendo cualquier orden de clasificación que pudiera haber existido.