doc: Replace some uses of "which" by "that" in parallel.sgml

This makes the documentation more accurate grammatically.

Author: Elena Indrupskaya
Discussion: https://postgr.es/m/1c994b3d-951e-59bb-1ac2-7b9221c0e4cf@postgrespro.ru
Backpatch-through: 9.6
This commit is contained in:
Michael Paquier 2021-09-02 11:36:01 +09:00
parent b51985d8a0
commit e976cc4a79
1 changed files with 26 additions and 26 deletions

View File

@ -8,11 +8,11 @@
</indexterm> </indexterm>
<para> <para>
<productname>PostgreSQL</productname> can devise query plans which can leverage <productname>PostgreSQL</productname> can devise query plans that can leverage
multiple CPUs in order to answer queries faster. This feature is known multiple CPUs in order to answer queries faster. This feature is known
as parallel query. Many queries cannot benefit from parallel query, either as parallel query. Many queries cannot benefit from parallel query, either
due to limitations of the current implementation or because there is no due to limitations of the current implementation or because there is no
imaginable query plan which is any faster than the serial query plan. imaginable query plan that is any faster than the serial query plan.
However, for queries that can benefit, the speedup from parallel query However, for queries that can benefit, the speedup from parallel query
is often very significant. Many queries can run more than twice as fast is often very significant. Many queries can run more than twice as fast
when using parallel query, and some queries can run four times faster or when using parallel query, and some queries can run four times faster or
@ -27,7 +27,7 @@
<para> <para>
When the optimizer determines that parallel query is the fastest execution When the optimizer determines that parallel query is the fastest execution
strategy for a particular query, it will create a query plan which includes strategy for a particular query, it will create a query plan that includes
a <firstterm>Gather</firstterm> or <firstterm>Gather Merge</firstterm> a <firstterm>Gather</firstterm> or <firstterm>Gather Merge</firstterm>
node. Here is a simple example: node. Here is a simple example:
@ -59,7 +59,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<para> <para>
<link linkend="using-explain">Using EXPLAIN</link>, you can see the number of <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 workers chosen by the planner. When the <literal>Gather</literal> node is reached
during query execution, the process which is implementing the user's during query execution, the process that is implementing the user's
session will request a number of <link linkend="bgworker">background session will request a number of <link linkend="bgworker">background
worker processes</link> equal to the number worker processes</link> equal to the number
of workers chosen by the planner. The number of background workers that of workers chosen by the planner. The number of background workers that
@ -79,7 +79,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
</para> </para>
<para> <para>
Every background worker process which is successfully started for a given Every background worker process that is successfully started for a given
parallel query will execute the parallel portion of the plan. The leader 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 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 responsibility: it must also read all of the tuples generated by the
@ -88,7 +88,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
worker, speeding up query execution. Conversely, when the parallel portion worker, speeding up query execution. Conversely, when the parallel portion
of the plan generates a large number of tuples, the leader may be almost 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 entirely occupied with reading the tuples generated by the workers and
performing any further processing steps which are required by plan nodes performing any further processing steps that are required by plan nodes
above the level of the <literal>Gather</literal> node or above the level of the <literal>Gather</literal> node or
<literal>Gather Merge</literal> node. In such cases, the leader will <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. do very little of the work of executing the parallel portion of the plan.
@ -109,7 +109,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<title>When Can Parallel Query Be Used?</title> <title>When Can Parallel Query Be Used?</title>
<para> <para>
There are several settings which can cause the query planner not to There are several settings that can cause the query planner not to
generate a parallel query plan under any circumstances. In order for generate a parallel query plan under any circumstances. In order for
any parallel query plans whatsoever to be generated, the following any parallel query plans whatsoever to be generated, the following
settings must be configured as indicated. settings must be configured as indicated.
@ -119,7 +119,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<listitem> <listitem>
<para> <para>
<xref linkend="guc-max-parallel-workers-per-gather"/> must be set to a <xref linkend="guc-max-parallel-workers-per-gather"/> must be set to a
value which is greater than zero. This is a special case of the more value that is greater than zero. This is a special case of the more
general principle that no more workers should be used than the number general principle that no more workers should be used than the number
configured via <varname>max_parallel_workers_per_gather</varname>. configured via <varname>max_parallel_workers_per_gather</varname>.
</para> </para>
@ -145,7 +145,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
contains a data-modifying operation either at the top level or within contains a data-modifying operation either at the top level or within
a CTE, no parallel plans for that query will be generated. As an a CTE, no parallel plans for that query will be generated. As an
exception, the commands <literal>CREATE TABLE ... AS</literal>, <literal>SELECT exception, the commands <literal>CREATE TABLE ... AS</literal>, <literal>SELECT
INTO</literal>, and <literal>CREATE MATERIALIZED VIEW</literal> which create a new INTO</literal>, and <literal>CREATE MATERIALIZED VIEW</literal> that create a new
table and populate it can use a parallel plan. table and populate it can use a parallel plan.
</para> </para>
</listitem> </listitem>
@ -240,7 +240,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
than normal but would produce incorrect results. Instead, the parallel than normal but would produce incorrect results. Instead, the parallel
portion of the plan must be what is known internally to the query portion of the plan must be what is known internally to the query
optimizer as a <firstterm>partial plan</firstterm>; that is, it must be constructed optimizer as a <firstterm>partial plan</firstterm>; that is, it must be constructed
so that each process which executes the plan will generate only a so that each process that executes the plan will generate only a
subset of the output rows in such a way that each required output row subset of the output rows in such a way that each required output row
is guaranteed to be generated by exactly one of the cooperating processes. is guaranteed to be generated by exactly one of the cooperating processes.
Generally, this means that the scan on the driving table of the query Generally, this means that the scan on the driving table of the query
@ -350,11 +350,11 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<para> <para>
Because the <literal>Finalize Aggregate</literal> node runs on the leader Because the <literal>Finalize Aggregate</literal> node runs on the leader
process, queries which produce a relatively large number of groups in process, queries that produce a relatively large number of groups in
comparison to the number of input rows will appear less favorable to the comparison to the number of input rows will appear less favorable to the
query planner. For example, in the worst-case scenario the number of query planner. For example, in the worst-case scenario the number of
groups seen by the <literal>Finalize Aggregate</literal> node could be as many as groups seen by the <literal>Finalize Aggregate</literal> node could be as many as
the number of input rows which were seen by all worker processes in the the number of input rows that were seen by all worker processes in the
<literal>Partial Aggregate</literal> stage. For such cases, there is clearly <literal>Partial Aggregate</literal> stage. For such cases, there is clearly
going to be no performance benefit to using parallel aggregation. The going to be no performance benefit to using parallel aggregation. The
query planner takes this into account during the planning process and is query planner takes this into account during the planning process and is
@ -410,7 +410,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
involve appending multiple results sets can therefore achieve involve appending multiple results sets can therefore achieve
coarse-grained parallelism even when efficient partial plans are not coarse-grained parallelism even when efficient partial plans are not
available. For example, consider a query against a partitioned table available. For example, consider a query against a partitioned table
which can only be implemented efficiently by using an index that does that can only be implemented efficiently by using an index that does
not support parallel scans. The planner might choose a <literal>Parallel not support parallel scans. The planner might choose a <literal>Parallel
Append</literal> of regular <literal>Index Scan</literal> plans; each Append</literal> of regular <literal>Index Scan</literal> plans; each
individual index scan would have to be executed to completion by a single individual index scan would have to be executed to completion by a single
@ -431,7 +431,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
If a query that is expected to do so does not produce a parallel plan, If a query that is expected to do so does not produce a parallel plan,
you can try reducing <xref linkend="guc-parallel-setup-cost"/> or you can try reducing <xref linkend="guc-parallel-setup-cost"/> or
<xref linkend="guc-parallel-tuple-cost"/>. Of course, this plan may turn <xref linkend="guc-parallel-tuple-cost"/>. Of course, this plan may turn
out to be slower than the serial plan which the planner preferred, but out to be slower than the serial plan that the planner preferred, but
this will not always be the case. If you don't get a parallel this will not always be the case. If you don't get a parallel
plan even with very small values of these settings (e.g., after setting plan even with very small values of these settings (e.g., after setting
them both to zero), there may be some reason why the query planner is them both to zero), there may be some reason why the query planner is
@ -458,15 +458,15 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<para> <para>
The planner classifies operations involved in a query as either The planner classifies operations involved in a query as either
<firstterm>parallel safe</firstterm>, <firstterm>parallel restricted</firstterm>, <firstterm>parallel safe</firstterm>, <firstterm>parallel restricted</firstterm>,
or <firstterm>parallel unsafe</firstterm>. A parallel safe operation is one which or <firstterm>parallel unsafe</firstterm>. A parallel safe operation is one that
does not conflict with the use of parallel query. A parallel restricted 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 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, can be performed in the leader while parallel query is in use. Therefore,
parallel restricted operations can never occur below a <literal>Gather</literal> parallel restricted operations can never occur below a <literal>Gather</literal>
or <literal>Gather Merge</literal> node, but can occur elsewhere in a plan which or <literal>Gather Merge</literal> node, but can occur elsewhere in a plan that
contains such a node. A parallel unsafe operation is one which cannot 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. be performed while parallel query is in use, not even in the leader.
When a query contains anything which is parallel unsafe, parallel query When a query contains anything that is parallel unsafe, parallel query
is completely disabled for that query. is completely disabled for that query.
</para> </para>
@ -490,7 +490,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<listitem> <listitem>
<para> <para>
Scans of foreign tables, unless the foreign data wrapper has Scans of foreign tables, unless the foreign data wrapper has
an <literal>IsForeignScanParallelSafe</literal> API which indicates otherwise. an <literal>IsForeignScanParallelSafe</literal> API that indicates otherwise.
</para> </para>
</listitem> </listitem>
@ -502,7 +502,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<listitem> <listitem>
<para> <para>
Plan nodes which reference a correlated <literal>SubPlan</literal>. Plan nodes that reference a correlated <literal>SubPlan</literal>.
</para> </para>
</listitem> </listitem>
</itemizedlist> </itemizedlist>
@ -513,7 +513,7 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<para> <para>
The planner cannot automatically determine whether a user-defined The planner cannot automatically determine whether a user-defined
function or aggregate is parallel safe, parallel restricted, or parallel function or aggregate is parallel safe, parallel restricted, or parallel
unsafe, because this would require predicting every operation which the unsafe, because this would require predicting every operation that the
function could possibly perform. In general, this is equivalent to the function could possibly perform. In general, this is equivalent to the
Halting Problem and therefore impossible. Even for simple functions Halting Problem and therefore impossible. Even for simple functions
where it could conceivably be done, we do not try, since this would be expensive where it could conceivably be done, we do not try, since this would be expensive
@ -531,11 +531,11 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
<para> <para>
Functions and aggregates must be marked <literal>PARALLEL UNSAFE</literal> if Functions and aggregates must be marked <literal>PARALLEL UNSAFE</literal> if
they write to the database, access sequences, change the transaction state they write to the database, access sequences, change the transaction state
even temporarily (e.g., a PL/pgSQL function which establishes an even temporarily (e.g., a PL/pgSQL function that establishes an
<literal>EXCEPTION</literal> block to catch errors), or make persistent changes to <literal>EXCEPTION</literal> block to catch errors), or make persistent changes to
settings. Similarly, functions must be marked <literal>PARALLEL settings. Similarly, functions must be marked <literal>PARALLEL
RESTRICTED</literal> if they access temporary tables, client connection state, RESTRICTED</literal> if they access temporary tables, client connection state,
cursors, prepared statements, or miscellaneous backend-local state which cursors, prepared statements, or miscellaneous backend-local state that
the system cannot synchronize across workers. For example, the system cannot synchronize across workers. For example,
<literal>setseed</literal> and <literal>random</literal> are parallel restricted for <literal>setseed</literal> and <literal>random</literal> are parallel restricted for
this last reason. this last reason.
@ -553,10 +553,10 @@ EXPLAIN SELECT * FROM pgbench_accounts WHERE filler LIKE '%x%';
</para> </para>
<para> <para>
If a function executed within a parallel worker acquires locks which are 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 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 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 transaction. If you write a function that does this, and this behavior
difference is important to you, mark such functions as difference is important to you, mark such functions as
<literal>PARALLEL RESTRICTED</literal> <literal>PARALLEL RESTRICTED</literal>
to ensure that they execute only in the leader. to ensure that they execute only in the leader.