The planner classifies operations involved in a query as either
<firstterm>parallel safe</firstterm>, <firstterm>parallel restricted</firstterm>,
or <firstterm>parallel unsafe</firstterm>. A parallel safe operation is one that
does not conflict with the use of parallel query. A parallel restricted
operation is one that cannot be performed in a parallel worker, but that
can be performed in the leader while parallel query is in use. Therefore,
parallel restricted operations can never occur below a <literal>Gather</literal>
or <literal>Gather Merge</literal> node, but can occur elsewhere in a plan that
contains such a node. A parallel unsafe operation is one that cannot
be performed while parallel query is in use, not even in the leader.
When a query contains anything that is parallel unsafe, parallel query
is completely disabled for that query.
プランナは、クエリ中に実行される操作をパラレル安全(parallel safe)、パラレル制限(parallel restricted)、パラレル非安全(parallel unsafe)に分類します。
パラレル安全操作は、パラレルクエリとコンフリクトしない操作です。
パラレル制限操作は、パラレルクエリを利用中に、パラレルワーカー中では実行できないが、リーダーによって実行できる操作です。
したがって、パラレル制限操作は、Gather
あるいはGather Merge
ノードより下では決して実行されませんが、Gather
ノードを含むプランの別の場所では実行されるかもしれません。
パラレル非安全操作は、パラレルクエリ利用中に、リーダーも含めて実行できない操作です。
クエリがパラレル非安全なものを含む場合は、クエリ中でのパラレルクエリの利用は全くできなくなります。
The following operations are always parallel restricted: 次の操作は常にパラレル制限です。
Scans of common table expressions (CTEs). 共通テーブル式(CTE)のスキャン
Scans of temporary tables. 一時テーブルのスキャン
Scans of foreign tables, unless the foreign data wrapper has
an <literal>IsForeignScanParallelSafe</literal> API that indicates otherwise.
外部テーブルのスキャン。
外部データラッパーがIsForeignScanParallelSafe
APIを持ち、パラレル安全を返す場合を除く。
Plan nodes to which an <literal>InitPlan</literal> is attached.
InitPlan
が付加されたプランノード
Plan nodes that reference a correlated <literal>SubPlan</literal>.
関連する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 that the
function could possibly perform. In general, this is equivalent to the
Halting Problem and therefore impossible. Even for simple functions
where it could 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
<xref linkend="sql-createfunction"/> or
<xref linkend="sql-alterfunction"/>, markings can be set by specifying
<literal>PARALLEL SAFE</literal>, <literal>PARALLEL RESTRICTED</literal>, or
<literal>PARALLEL UNSAFE</literal> as appropriate. When using
<xref linkend="sql-createaggregate"/>, the
<literal>PARALLEL</literal> option can be specified with <literal>SAFE</literal>,
<literal>RESTRICTED</literal>, or <literal>UNSAFE</literal> as the corresponding value.
プランナは、自動的にはユーザ定義関数や集約がパラレル安全か、パラレル制限か、あるいはパラレル非安全かを決定することはできません。
この関数が潜在的に実行する可能性のあるすべての操作を予測することが、このために要求されるからです。
一般的には、これは停止性問題と同等で、それ故に不可能です。
おそらく終了できると思われる単純な関数においてさえ、私達は試みません。なぜなら、そうした予測は高価でエラーを起こしやすいからです。
その代わりに、そうではないとマークされない限り、すべてのユーザ定義関数は、パラレル非安全と見なされます。
CREATE FUNCTIONあるいはALTER FUNCTIONを使用するときは、
適当なPARALLEL SAFE
、PARALLEL RESTRICTED
、PARALLEL UNSAFE
を指定することによってマーキングを行うことができます。
CREATE AGGREGATEを利用するときは、対応する値にしたがって、SAFE
、RESTRICTED
、UNSAFE
のどれかをPARALLEL
オプションに指定します。
Functions and aggregates must be marked <literal>PARALLEL UNSAFE</literal>
if they write to the database, change the transaction state (other than by
using a subtransaction for error recovery), access sequences, or make
persistent changes to
settings. Similarly, functions must be marked <literal>PARALLEL
RESTRICTED</literal> if they access temporary tables, client connection state,
cursors, prepared statements, or miscellaneous backend-local state that
the system cannot synchronize across workers. For example,
<literal>setseed</literal> and <literal>random</literal> are parallel restricted for
this last reason.
関数あるいは集約は、データベースに書き込むか、(エラー回復のためにサブトランザクションを使う場合以外で)トランザクションの状態を変更するか、シーケンスにアクセスするか、あるいは、恒久的な設定変更を行う場合、PARALLEL UNSAFE
とマークされなければなりません。
同様に関数は、一時テーブル、クライアントの接続状態、カーソル、準備された文、システムがワーカーの間で同期できないその他のバックエンドローカルな状態にアクセスする場合、PARALLEL RESTRICTED
とマークされなければなりません。
たとえば、setseed
とrandom
は、最後の理由により、パラレル制限です。
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 <literal>UNSAFE</literal>.
一般的に制限あるいは非安全な関数が安全とラベル付されたり、実際には非安全なのに制限付きとラベル付されると、パラレルクエリの中で使用される際に、エラーを生じたり、間違った結果を生成するかもしれません。
誤ったラベル付をされると、C言語関数は理論的にはまったく未定義の振る舞いを示すことがあります。
システムは任意のCコードから身を守るすべがないからです。
しかしもっとも起こりえる可能性としては、他の関数のよりも悪いということはなさそうです。
もし自信がないなら、たぶんその関数をUNSAFE
とラベル付するのが最善でしょう。
If a function executed within a parallel worker acquires locks that 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 that does this, and this behavior
difference is important to you, mark such functions as
<literal>PARALLEL RESTRICTED</literal>
to ensure that they execute only in the leader.
パラレルワーカーの中で実行される関数がリーダーが獲得していないロックを獲得する場合、たとえばクエリ中で参照されていないテーブルに対して問い合わせを実行する場合などは、これらのロックはトランザクションが終了した時点ではなく、ワーカーが終了する際に解放されます。
もしあなたがこれを行う関数を作成し、こうした振る舞いの違いがあなたにとって重要ならば、関数がリーダーの中だけで実行されることを保証するために、関数をPARALLEL RESTRICTED
とマーク付けしてください。
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 <literal>WHERE</literal>
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
<literal>WHERE</literal> clause so that it happens above the <literal>Gather</literal>
node. However, the planner does not do this.
より良いプランを得るために、プランナがクエリの中で実行されるパラレル制限な関数や集約の評価の遅延を考慮することはないことに注意してください。
したがって、たとえばあるテーブルに適用されるWHERE
句がパラレル制限であるときに、クエリプランナはプランの並列実行部分中のテーブルに対してスキャンを実行をすることを考慮しません。
ある場合においては、クエリ中のパラレル部分におけるテーブルのスキャンを含むようにして、WHERE
句の評価を遅らせ、Gather
ノード上で実行されるようにすることも可能でしょう(そしてその方が効率が良いことさえあります)。
しかし、プランナはそうしたことは行いません。