The planner classifies operations involved in a query as either
parallel safe, parallel restricted, or parallel unsafe. A parallel safe operation is one
which does not conflict with the use of parallel query. A parallel
restricted operation is one which cannot be performed in a parallel
worker, but which can be performed in the leader while parallel
query is in use. Therefore, parallel restricted operations can
never occur below a Gather
or
Gather Merge
node, but can occur
elsewhere in a plan which contains such a node. A parallel unsafe
operation is one which cannot be performed while parallel query is
in use, not even in the leader. When a query contains anything
which is parallel unsafe, parallel query is completely disabled for
that query.
The following operations are always parallel restricted.
Scans of common table expressions (CTEs).
Scans of temporary tables.
Scans of foreign tables, unless the foreign data wrapper has an
IsForeignScanParallelSafe
API which
indicates otherwise.
Access to an InitPlan
or correlated
SubPlan
.
The planner cannot automatically determine whether a
user-defined function or aggregate is parallel safe, parallel
restricted, or parallel unsafe, because this would require
predicting every operation which the function could possibly
perform. In general, this is equivalent to the Halting Problem and
therefore impossible. Even for simple functions where it
conceivably be done, we do not try, since this would be expensive
and error-prone. Instead, all user-defined functions are assumed to
be parallel unsafe unless otherwise marked. When using CREATE
FUNCTION or ALTER FUNCTION, markings can be set by
specifying PARALLEL SAFE
, PARALLEL RESTRICTED
, or PARALLEL UNSAFE
as appropriate. When using
CREATE
AGGREGATE, the PARALLEL
option can be specified with SAFE
,
RESTRICTED
, or UNSAFE
as the corresponding value.
Functions and aggregates must be marked PARALLEL UNSAFE
if they write to the database,
access sequences, change the transaction state even temporarily
(e.g. a PL/pgSQL function which establishes an EXCEPTION
block to catch errors), or make
persistent changes to settings. Similarly, functions must be marked
PARALLEL RESTRICTED
if they access
temporary tables, client connection state, cursors, prepared
statements, or miscellaneous backend-local state which the system
cannot synchronize across workers. For example, setseed
and random
are parallel restricted for this last reason.
In general, if a function is labeled as being safe when it is
restricted or unsafe, or if it is labeled as being restricted when
it is in fact unsafe, it may throw errors or produce wrong answers
when used in a parallel query. C-language functions could in theory
exhibit totally undefined behavior if mislabeled, since there is no
way for the system to protect itself against arbitrary C code, but
in most likely cases the result will be no worse than for any other
function. If in doubt, it is probably best to label functions as
UNSAFE
.
If a function executed within a parallel worker acquires locks
which are not held by the leader, for example by querying a table
not referenced in the query, those locks will be released at worker
exit, not end of transaction. If you write a function which does
this, and this behavior difference is important to you, mark such
functions as PARALLEL RESTRICTED
to
ensure that they execute only in the leader.
Note that the query planner does not consider deferring the
evaluation of parallel-restricted functions or aggregates involved
in the query in order to obtain a superior plan. So, for example,
if a WHERE
clause applied to a
particular table is parallel restricted, the query planner will not
consider performing a scan of that table in the parallel portion of
a plan. In some cases, it would be possible (and perhaps even
efficient) to include the scan of that table in the parallel
portion of the query and defer the evaluation of the WHERE
clause so that it happens above the
Gather
node. However, the planner does
not do this.
If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.