Skip to content

Commit 355d399

Browse files
committed
Add a Gather Merge executor node.
Like Gather, we spawn multiple workers and run the same plan in each one; however, Gather Merge is used when each worker produces the same output ordering and we want to preserve that output ordering while merging together the streams of tuples from various workers. (In a way, Gather Merge is like a hybrid of Gather and MergeAppend.) This works out to a win if it saves us from having to perform an expensive Sort. In cases where only a small amount of data would need to be sorted, it may actually be faster to use a regular Gather node and then sort the results afterward, because Gather Merge sometimes needs to wait synchronously for tuples whereas a pure Gather generally doesn't. But if this avoids an expensive sort then it's a win. Rushabh Lathia, reviewed and tested by Amit Kapila, Thomas Munro, and Neha Sharma, and reviewed and revised by me. Discussion: http://postgr.es/m/CAGPqQf09oPX-cQRpBKS0Gq49Z+m6KBxgxd_p9gX8CKk_d75HoQ@mail.gmail.com
1 parent a72f036 commit 355d399

27 files changed

+1355
-16
lines changed

doc/src/sgml/config.sgml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3497,6 +3497,20 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
34973497
</listitem>
34983498
</varlistentry>
34993499

3500+
<varlistentry id="guc-enable-gathermerge" xreflabel="enable_gathermerge">
3501+
<term><varname>enable_gathermerge</varname> (<type>boolean</type>)
3502+
<indexterm>
3503+
<primary><varname>enable_gathermerge</> configuration parameter</primary>
3504+
</indexterm>
3505+
</term>
3506+
<listitem>
3507+
<para>
3508+
Enables or disables the query planner's use of gather
3509+
merge plan types. The default is <literal>on</>.
3510+
</para>
3511+
</listitem>
3512+
</varlistentry>
3513+
35003514
<varlistentry id="guc-enable-hashagg" xreflabel="enable_hashagg">
35013515
<term><varname>enable_hashagg</varname> (<type>boolean</type>)
35023516
<indexterm>

src/backend/commands/explain.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,9 @@ ExplainNode(PlanState *planstate, List *ancestors,
918918
case T_Gather:
919919
pname = sname = "Gather";
920920
break;
921+
case T_GatherMerge:
922+
pname = sname = "Gather Merge";
923+
break;
921924
case T_IndexScan:
922925
pname = sname = "Index Scan";
923926
break;
@@ -1411,6 +1414,26 @@ ExplainNode(PlanState *planstate, List *ancestors,
14111414
ExplainPropertyBool("Single Copy", gather->single_copy, es);
14121415
}
14131416
break;
1417+
case T_GatherMerge:
1418+
{
1419+
GatherMerge *gm = (GatherMerge *) plan;
1420+
1421+
show_scan_qual(plan->qual, "Filter", planstate, ancestors, es);
1422+
if (plan->qual)
1423+
show_instrumentation_count("Rows Removed by Filter", 1,
1424+
planstate, es);
1425+
ExplainPropertyInteger("Workers Planned",
1426+
gm->num_workers, es);
1427+
if (es->analyze)
1428+
{
1429+
int nworkers;
1430+
1431+
nworkers = ((GatherMergeState *) planstate)->nworkers_launched;
1432+
ExplainPropertyInteger("Workers Launched",
1433+
nworkers, es);
1434+
}
1435+
}
1436+
break;
14141437
case T_FunctionScan:
14151438
if (es->verbose)
14161439
{

src/backend/executor/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ OBJS = execAmi.o execCurrent.o execGrouping.o execIndexing.o execJunk.o \
2020
nodeBitmapHeapscan.o nodeBitmapIndexscan.o \
2121
nodeCustom.o nodeFunctionscan.o nodeGather.o \
2222
nodeHash.o nodeHashjoin.o nodeIndexscan.o nodeIndexonlyscan.o \
23-
nodeLimit.o nodeLockRows.o \
23+
nodeLimit.o nodeLockRows.o nodeGatherMerge.o \
2424
nodeMaterial.o nodeMergeAppend.o nodeMergejoin.o nodeModifyTable.o \
2525
nodeNestloop.o nodeProjectSet.o nodeRecursiveunion.o nodeResult.o \
2626
nodeSamplescan.o nodeSeqscan.o nodeSetOp.o nodeSort.o nodeUnique.o \

src/backend/executor/execProcnode.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
#include "executor/nodeForeignscan.h"
9090
#include "executor/nodeFunctionscan.h"
9191
#include "executor/nodeGather.h"
92+
#include "executor/nodeGatherMerge.h"
9293
#include "executor/nodeGroup.h"
9394
#include "executor/nodeHash.h"
9495
#include "executor/nodeHashjoin.h"
@@ -326,6 +327,11 @@ ExecInitNode(Plan *node, EState *estate, int eflags)
326327
estate, eflags);
327328
break;
328329

330+
case T_GatherMerge:
331+
result = (PlanState *) ExecInitGatherMerge((GatherMerge *) node,
332+
estate, eflags);
333+
break;
334+
329335
case T_Hash:
330336
result = (PlanState *) ExecInitHash((Hash *) node,
331337
estate, eflags);
@@ -535,6 +541,10 @@ ExecProcNode(PlanState *node)
535541
result = ExecGather((GatherState *) node);
536542
break;
537543

544+
case T_GatherMergeState:
545+
result = ExecGatherMerge((GatherMergeState *) node);
546+
break;
547+
538548
case T_HashState:
539549
result = ExecHash((HashState *) node);
540550
break;
@@ -697,6 +707,10 @@ ExecEndNode(PlanState *node)
697707
ExecEndGather((GatherState *) node);
698708
break;
699709

710+
case T_GatherMergeState:
711+
ExecEndGatherMerge((GatherMergeState *) node);
712+
break;
713+
700714
case T_IndexScanState:
701715
ExecEndIndexScan((IndexScanState *) node);
702716
break;
@@ -842,6 +856,9 @@ ExecShutdownNode(PlanState *node)
842856
case T_CustomScanState:
843857
ExecShutdownCustomScan((CustomScanState *) node);
844858
break;
859+
case T_GatherMergeState:
860+
ExecShutdownGatherMerge((GatherMergeState *) node);
861+
break;
845862
default:
846863
break;
847864
}

0 commit comments

Comments
 (0)