El planificador clasifica las operaciones involucradas en una consulta como seguras para paralelismo (parallel safe), restringidas para paralelismo (parallel restricted) o inseguras para paralelismo (parallel unsafe). Una operación segura para paralelismo es aquella que no entra en conflicto con el uso de consultas en paralelo. Una operación restringida para paralelismo es aquella que no se puede realizar en un trabajador paralelo, pero que se puede realizar en el líder mientras se utilizan consultas en paralelo. Por lo tanto, las operaciones restringidas para paralelismo nunca pueden ocurrir por debajo de un nodo Gather o Gather Merge, pero pueden ocurrir en cualquier otra parte de un plan que contenga dicho nodo. Una operación unsafe para paralelismo es aquella que no se puede realizar mientras se utilizan consultas en paralelo, ni siquiera en el líder. Cuando una consulta contiene algo que es inseguro para paralelismo, las consultas en paralelo se desactivan por completo para esa consulta.
Las siguientes operaciones siempre están restringidas para paralelismo:
Escaneos de expresiones de tabla comunes (CTEs).
Escaneos de tablas temporales.
Escaneos de tablas extranjeras (foreign tables), a menos que el conector de datos externos (foreign data wrapper)
tenga una API IsForeignScanParallelSafe que indique lo contrario.
Nodos de plan que hacen referencia a una subconsulta correlacionada (SubPlan).
El planificador no puede determinar automáticamente si una función o agregación definida por el usuario
es segura, restringida o insegura para paralelismo, porque esto requeriría predecir cada operación que la
función podría llegar a realizar. En general, esto equivale al problema de la parada (Halting Problem) y,
por lo tanto, es imposible. Incluso para funciones simples donde concebiblemente se podría hacer, no lo
intentamos, ya que sería costoso y propenso a errores. En su lugar, se asume que todas las funciones definidas
por el usuario son inseguras para paralelismo a menos que se indique lo contrario. Al usar
CREATE FUNCTION o ALTER FUNCTION, se pueden establecer las etiquetas
especificando PARALLEL SAFE, PARALLEL RESTRICTED o
PARALLEL UNSAFE según corresponda. Al usar CREATE AGGREGATE, se puede
especificar la opción PARALLEL con SAFE, RESTRICTED
o UNSAFE como su valor correspondiente.
Las funciones y agregaciones deben marcarse como PARALLEL UNSAFE si escriben en la base
de datos, cambian el estado de la transacción (salvo al usar una subtransacción para la recuperación de errores),
acceden a secuencias o realizan cambios persistentes en la configuración. Del mismo modo, las funciones deben
marcarse como PARALLEL RESTRICTED si acceden a tablas temporales, al estado de la conexión
del cliente, a cursores, a sentencias preparadas o a estados locales del backend diversos que el sistema no puede
sincronizar entre los trabajadores. Por ejemplo, setseed y random son
restringidas para paralelismo por esta última razón.
En general, si una función se etiqueta como segura cuando en realidad es restringida o insegura, o si se etiqueta
como restringida cuando en realidad es insegura, puede arrojar errores o producir respuestas incorrectas cuando
se use en una consulta paralela. Las funciones en lenguaje C podrían, en teoría, exhibir un comportamiento totalmente
indefinido si se etiquetan incorrectamente, ya que no hay forma de que el sistema se proteja contra el código C arbitrario,
pero en la mayoría de los casos probables el resultado no será peor que para cualquier otra función. En caso de duda,
lo mejor es etiquetar las funciones como UNSAFE.
Si una función ejecutada dentro de un trabajador paralelo adquiere bloqueos que no están en posesión del líder,
por ejemplo, al consultar una tabla que no está referenciada en la consulta, esos bloqueos se liberarán al salir el
trabajador, no al final de la transacción. Si escribes una función que hace esto y esta diferencia de comportamiento
es importante para ti, marca tales funciones como PARALLEL RESTRICTED para asegurar que se
ejecuten solo en el líder.
Ten en cuenta que el planificador de consultas no considera posponer la evaluación de funciones o agregaciones
restringidas para paralelismo involucradas en la consulta para obtener un plan superior. Por lo tanto, por ejemplo,
si una cláusula WHERE aplicada a una tabla en particular está restringida para paralelismo, el
planificador de consultas no considerará realizar un escaneo de esa tabla en la porción paralela de un plan.
En algunos casos, sería posible (y quizás incluso eficiente) incluir el escaneo de esa tabla en la porción paralela
de la consulta y posponer la evaluación de la cláusula WHERE para que ocurra por encima del nodo
Gather. Sin embargo, the planner no hace esto.