バージョンごとのドキュメント一覧

15.1. パラレルクエリはどのように動くのか #

<title>How Parallel Query Works</title>

When the optimizer determines that parallel query is the fastest execution strategy for a particular query, it will create a query plan that includes a <firstterm>Gather</firstterm> or <firstterm>Gather Merge</firstterm> node. Here is a simple example: あるクエリの最速の実行戦略がパラレルクエリであるとオプティマイザが決定すると、GatherまたはGather Mergeノードを含むクエリプランを作成します。 単純な例を示します。

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)

In all cases, the <literal>Gather</literal> or <literal>Gather Merge</literal> node will have exactly one child plan, which is the portion of the plan that will be executed in parallel. If the <literal>Gather</literal> or <literal>Gather Merge</literal> node is at the very top of the plan tree, then the entire query will execute in parallel. If it is somewhere else in the plan tree, then only the portion of the plan below it will run in parallel. In the example above, the query accesses only one table, so there is only one plan node other than the <literal>Gather</literal> node itself; since that plan node is a child of the <literal>Gather</literal> node, it will run in parallel. どの場合でも、GatherまたはGather Mergeノードは、正確に一つの子ノードを持ちます。 子プランは、プランの中で並列に実行される部分です。 GatherまたはGather Mergeノードがプランツリーの中で最上位にある場合は、クエリ全体が並列に実行されます。 GatherまたはGather Mergeノードがプランツリーの他の部分にある場合は、その部分だけが並列に実行されます。 上の例では、クエリはただ一つのテーブルにアクセスするので、Gatherノード自身以外では、たった一つのプランノードだけが存在します。 そのプランノードはGatherノードの子ノードなので、並列に実行されます。

<link linkend="using-explain">Using EXPLAIN</link>, you can see the number of workers chosen by the planner. When the <literal>Gather</literal> node is reached during query execution, the process that is implementing the user's session will request a number of <link linkend="bgworker">background worker processes</link> equal to the number of workers chosen by the planner. The number of background workers that the planner will consider using is limited to at most <xref linkend="guc-max-parallel-workers-per-gather"/>. The total number of background workers that can exist at any one time is limited by both <xref linkend="guc-max-worker-processes"/> and <xref linkend="guc-max-parallel-workers"/>. Therefore, it is possible for a parallel query to run with fewer workers than planned, or even with no workers at all. The optimal plan may depend on the number of workers that are available, so this can result in poor query performance. If this occurrence is frequent, consider increasing <varname>max_worker_processes</varname> and <varname>max_parallel_workers</varname> so that more workers can be run simultaneously or alternatively reducing <varname>max_parallel_workers_per_gather</varname> so that the planner requests fewer workers. EXPLAINを使って、プランナが選択したワーカーの数を見ることができます。 クエリの実行中にGatherノードに到達すると、ユーザのセッションに対応しているプロセスは、プランナが選択したワーカーと同じ数のバックグラウンドワーカープロセスを要求します。 プランナが使用を検討するバックグラウンドワーカーの数は、最大でもmax_parallel_workers_per_gatherに制限されます。 ある時点で存在できるバックグラウンドワーカーの数は、max_worker_processesmax_parallel_workersの両方を満たすように制限されます。 ですから、あるパラレルクエリが、プラン時よりも少ない数のワーカープロセスによって実行されたり、まったくワーカープロセスなしに実行されることがあり得ます。 最適なプランは利用可能なワーカーの数に依存することもあるので、これは低い性能をもたらす結果になるかもしれません。 これがしばしば起こるようなら、max_worker_processesmax_parallel_workersを増やしてより多くのワーカーが同時に実行できるようにするか、 max_parallel_workers_per_gatherを減らして、プランナがより少ない数のワーカーを要求するようにすることを考慮してください。

Every background worker process that is successfully started for a given parallel query will execute the parallel portion of the plan. The leader will also execute that portion of the plan, but it has an additional responsibility: it must also read all of the tuples generated by the workers. When the parallel portion of the plan generates only a small number of tuples, the leader will often behave very much like an additional worker, speeding up query execution. Conversely, when the parallel portion of the plan generates a large number of tuples, the leader may be almost entirely occupied with reading the tuples generated by the workers and performing any further processing steps that are required by plan nodes above the level of the <literal>Gather</literal> node or <literal>Gather Merge</literal> node. In such cases, the leader will do very little of the work of executing the parallel portion of the plan. 与えられたパラレルクエリから起動されたすべてのバックグラウンドワーカープロセスは、そのプランの一部を実行します。 リーダーはそうしたプランの部分を実行するだけでなく、追加の任務が与えられます。 つまり、ワーカーが生成したすべてのタプルを読み込まなければなりません。 プラン中のパラレル部分が少数のタプルしか生成しない場合は、リーダーは追加のワーカーとほぼ同じように振る舞い、クエリの実行を高速化します。 反対にプラン中のパラレル部分が大量のタプルを生成する場合は、リーダーはワーカーが生成したタプルの読み込みと、GatherノードあるいはGather Mergeより上位のプランノードが要求する追加の処理ステップに忙殺されるかもしれません。 そのような場合は、リーダーはプランの並列実行部分のごく一部しか処理しません。

When the node at the top of the parallel portion of the plan is <literal>Gather Merge</literal> rather than <literal>Gather</literal>, it indicates that each process executing the parallel portion of the plan is producing tuples in sorted order, and that the leader is performing an order-preserving merge. In contrast, <literal>Gather</literal> reads tuples from the workers in whatever order is convenient, destroying any sort order that may have existed. プランの並列部分の最上位ノードがGatherではなくてGather Mergeなら、プランの並列部分を実行する各プロセスはタプルをソート順に生成し、リーダーはソート順を保存するマージを実行していることを意味します。 対照的に、Gatherは、ワーカーから都合の良い順でタプルを読み込むので、ソート順が存在しているとしても、それを壊してしまいます。