Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
parallel-plans.html155 linesDownload Raw Back to html
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>15.3. Parallel Plans</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="when-can-parallel-query-be-used.html" title="15.2. When Can Parallel Query Be Used?" /><link rel="next" href="parallel-safety.html" title="15.4. Parallel Safety" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">15.3. Parallel Plans</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="when-can-parallel-query-be-used.html" title="15.2. When Can Parallel Query Be Used?">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="parallel-query.html" title="Chapter 15. Parallel Query">Up</a></td><th width="60%" align="center">Chapter 15. Parallel Query</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 16.3 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="parallel-safety.html" title="15.4. Parallel Safety">Next</a></td></tr></table><hr /></div><div class="sect1" id="PARALLEL-PLANS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">15.3. Parallel Plans <a href="#PARALLEL-PLANS" class="id_link">#</a></h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="parallel-plans.html#PARALLEL-SCANS">15.3.1. Parallel Scans</a></span></dt><dt><span class="sect2"><a href="parallel-plans.html#PARALLEL-JOINS">15.3.2. Parallel Joins</a></span></dt><dt><span class="sect2"><a href="parallel-plans.html#PARALLEL-AGGREGATION">15.3.3. Parallel Aggregation</a></span></dt><dt><span class="sect2"><a href="parallel-plans.html#PARALLEL-APPEND">15.3.4. Parallel Append</a></span></dt><dt><span class="sect2"><a href="parallel-plans.html#PARALLEL-PLAN-TIPS">15.3.5. Parallel Plan Tips</a></span></dt></dl></div><p>3    Because each worker executes the parallel portion of the plan to4    completion, it is not possible to simply take an ordinary query plan5    and run it using multiple workers.  Each worker would produce a full6    copy of the output result set, so the query would not run any faster7    than normal but would produce incorrect results.  Instead, the parallel8    portion of the plan must be what is known internally to the query9    optimizer as a <em class="firstterm">partial plan</em>; that is, it must be constructed10    so that each process that executes the plan will generate only a11    subset of the output rows in such a way that each required output row12    is guaranteed to be generated by exactly one of the cooperating processes.13    Generally, this means that the scan on the driving table of the query14    must be a parallel-aware scan.15  </p><div class="sect2" id="PARALLEL-SCANS"><div class="titlepage"><div><div><h3 class="title">15.3.1. Parallel Scans <a href="#PARALLEL-SCANS" class="id_link">#</a></h3></div></div></div><p>16    The following types of parallel-aware table scans are currently supported.17 18  </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>19        In a <span class="emphasis"><em>parallel sequential scan</em></span>, the table's blocks will20        be divided into ranges and shared among the cooperating processes.  Each21        worker process will complete the scanning of its given range of blocks before22        requesting an additional range of blocks.23      </p></li><li class="listitem"><p>24        In a <span class="emphasis"><em>parallel bitmap heap scan</em></span>, one process is chosen25        as the leader.  That process performs a scan of one or more indexes26        and builds a bitmap indicating which table blocks need to be visited.27        These blocks are then divided among the cooperating processes as in28        a parallel sequential scan.  In other words, the heap scan is performed29        in parallel, but the underlying index scan is not.30      </p></li><li class="listitem"><p>31        In a <span class="emphasis"><em>parallel index scan</em></span> or <span class="emphasis"><em>parallel index-only32        scan</em></span>, the cooperating processes take turns reading data from the33        index.  Currently, parallel index scans are supported only for34        btree indexes.  Each process will claim a single index block and will35        scan and return all tuples referenced by that block; other processes can36        at the same time be returning tuples from a different index block.37        The results of a parallel btree scan are returned in sorted order38        within each worker process.39      </p></li></ul></div><p>40 41    Other scan types, such as scans of non-btree indexes, may support42    parallel scans in the future.43  </p></div><div class="sect2" id="PARALLEL-JOINS"><div class="titlepage"><div><div><h3 class="title">15.3.2. Parallel Joins <a href="#PARALLEL-JOINS" class="id_link">#</a></h3></div></div></div><p>44    Just as in a non-parallel plan, the driving table may be joined to one or45    more other tables using a nested loop, hash join, or merge join.  The46    inner side of the join may be any kind of non-parallel plan that is47    otherwise supported by the planner provided that it is safe to run within48    a parallel worker.  Depending on the join type, the inner side may also be49    a parallel plan.50  </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"><p>51        In a <span class="emphasis"><em>nested loop join</em></span>, the inner side is always52        non-parallel.  Although it is executed in full, this is efficient if53        the inner side is an index scan, because the outer tuples and thus54        the loops that look up values in the index are divided over the55        cooperating processes.56      </p></li><li class="listitem"><p>57        In a <span class="emphasis"><em>merge join</em></span>, the inner side is always58        a non-parallel plan and therefore executed in full.  This may be59        inefficient, especially if a sort must be performed, because the work60        and resulting data are duplicated in every cooperating process.61      </p></li><li class="listitem"><p>62        In a <span class="emphasis"><em>hash join</em></span> (without the "parallel" prefix),63        the inner side is executed in full by every cooperating process64        to build identical copies of the hash table.  This may be inefficient65        if the hash table is large or the plan is expensive.  In a66        <span class="emphasis"><em>parallel hash join</em></span>, the inner side is a67        <span class="emphasis"><em>parallel hash</em></span> that divides the work of building68        a shared hash table over the cooperating processes.69      </p></li></ul></div></div><div class="sect2" id="PARALLEL-AGGREGATION"><div class="titlepage"><div><div><h3 class="title">15.3.3. Parallel Aggregation <a href="#PARALLEL-AGGREGATION" class="id_link">#</a></h3></div></div></div><p>70    <span class="productname">PostgreSQL</span> supports parallel aggregation by aggregating in71    two stages.  First, each process participating in the parallel portion of72    the query performs an aggregation step, producing a partial result for73    each group of which that process is aware.  This is reflected in the plan74    as a <code class="literal">Partial Aggregate</code> node.  Second, the partial results are75    transferred to the leader via <code class="literal">Gather</code> or <code class="literal">Gather76    Merge</code>.  Finally, the leader re-aggregates the results across all77    workers in order to produce the final result.  This is reflected in the78    plan as a <code class="literal">Finalize Aggregate</code> node.79  </p><p>80    Because the <code class="literal">Finalize Aggregate</code> node runs on the leader81    process, queries that produce a relatively large number of groups in82    comparison to the number of input rows will appear less favorable to the83    query planner. For example, in the worst-case scenario the number of84    groups seen by the <code class="literal">Finalize Aggregate</code> node could be as many as85    the number of input rows that were seen by all worker processes in the86    <code class="literal">Partial Aggregate</code> stage. For such cases, there is clearly87    going to be no performance benefit to using parallel aggregation. The88    query planner takes this into account during the planning process and is89    unlikely to choose parallel aggregate in this scenario.90  </p><p>91    Parallel aggregation is not supported in all situations.  Each aggregate92    must be <a class="link" href="parallel-safety.html" title="15.4. Parallel Safety">safe</a> for parallelism and must93    have a combine function.  If the aggregate has a transition state of type94    <code class="literal">internal</code>, it must have serialization and deserialization95    functions.  See <a class="xref" href="sql-createaggregate.html" title="CREATE AGGREGATE"><span class="refentrytitle">CREATE AGGREGATE</span></a> for more details.96    Parallel aggregation is not supported if any aggregate function call97    contains <code class="literal">DISTINCT</code> or <code class="literal">ORDER BY</code> clause and is also98    not supported for ordered set aggregates or when  the query involves99    <code class="literal">GROUPING SETS</code>.  It can only be used when all joins involved in100    the query are also part of the parallel portion of the plan.101  </p></div><div class="sect2" id="PARALLEL-APPEND"><div class="titlepage"><div><div><h3 class="title">15.3.4. Parallel Append <a href="#PARALLEL-APPEND" class="id_link">#</a></h3></div></div></div><p>102    Whenever <span class="productname">PostgreSQL</span> needs to combine rows103    from multiple sources into a single result set, it uses an104    <code class="literal">Append</code> or <code class="literal">MergeAppend</code> plan node.105    This commonly happens when implementing <code class="literal">UNION ALL</code> or106    when scanning a partitioned table.  Such nodes can be used in parallel107    plans just as they can in any other plan.  However, in a parallel plan,108    the planner may instead use a <code class="literal">Parallel Append</code> node.109  </p><p>110    When an <code class="literal">Append</code> node is used in a parallel plan, each111    process will execute the child plans in the order in which they appear,112    so that all participating processes cooperate to execute the first child113    plan until it is complete and then move to the second plan at around the114    same time.  When a <code class="literal">Parallel Append</code> is used instead, the115    executor will instead spread out the participating processes as evenly as116    possible across its child plans, so that multiple child plans are executed117    simultaneously.  This avoids contention, and also avoids paying the startup118    cost of a child plan in those processes that never execute it.119  </p><p>120    Also, unlike a regular <code class="literal">Append</code> node, which can only have121    partial children when used within a parallel plan, a <code class="literal">Parallel122    Append</code> node can have both partial and non-partial child plans.123    Non-partial children will be scanned by only a single process, since124    scanning them more than once would produce duplicate results.  Plans that125    involve appending multiple results sets can therefore achieve126    coarse-grained parallelism even when efficient partial plans are not127    available.  For example, consider a query against a partitioned table128    that can only be implemented efficiently by using an index that does129    not support parallel scans.  The planner might choose a <code class="literal">Parallel130    Append</code> of regular <code class="literal">Index Scan</code> plans; each131    individual index scan would have to be executed to completion by a single132    process, but different scans could be performed at the same time by133    different processes.134  </p><p>135    <a class="xref" href="runtime-config-query.html#GUC-ENABLE-PARALLEL-APPEND">enable_parallel_append</a> can be used to disable136    this feature.137  </p></div><div class="sect2" id="PARALLEL-PLAN-TIPS"><div class="titlepage"><div><div><h3 class="title">15.3.5. Parallel Plan Tips <a href="#PARALLEL-PLAN-TIPS" class="id_link">#</a></h3></div></div></div><p>138    If a query that is expected to do so does not produce a parallel plan,139    you can try reducing <a class="xref" href="runtime-config-query.html#GUC-PARALLEL-SETUP-COST">parallel_setup_cost</a> or140    <a class="xref" href="runtime-config-query.html#GUC-PARALLEL-TUPLE-COST">parallel_tuple_cost</a>.  Of course, this plan may turn141    out to be slower than the serial plan that the planner preferred, but142    this will not always be the case.  If you don't get a parallel143    plan even with very small values of these settings (e.g., after setting144    them both to zero), there may be some reason why the query planner is145    unable to generate a parallel plan for your query.  See146    <a class="xref" href="when-can-parallel-query-be-used.html" title="15.2. When Can Parallel Query Be Used?">Section 15.2</a> and147    <a class="xref" href="parallel-safety.html" title="15.4. Parallel Safety">Section 15.4</a> for information on why this may be148    the case.149  </p><p>150    When executing a parallel plan, you can use <code class="literal">EXPLAIN (ANALYZE,151    VERBOSE)</code> to display per-worker statistics for each plan node.152    This may be useful in determining whether the work is being evenly153    distributed between all plan nodes and more generally in understanding the154    performance characteristics of the plan.155  </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="when-can-parallel-query-be-used.html" title="15.2. When Can Parallel Query Be Used?">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="parallel-query.html" title="Chapter 15. Parallel Query">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="parallel-safety.html" title="15.4. Parallel Safety">Next</a></td></tr><tr><td width="40%" align="left" valign="top">15.2. When Can Parallel Query Be Used? </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 16.3 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 15.4. Parallel Safety</td></tr></table></div></body></html>
codekingpro/portable-devtools · Team Ai