Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd8b1bf4

Browse files
committed
Create a new 'MultiExecProcNode' call API for plan nodes that don't
return just a single tuple at a time. Currently the only such nodetype is Hash, but I expect we will soon have indexscans that can returntuple bitmaps. A side benefit is that EXPLAIN ANALYZE now shows thecorrect tuple count for a Hash node.
1 parent85eee28 commitd8b1bf4

File tree

9 files changed

+121
-39
lines changed

9 files changed

+121
-39
lines changed

‎src/backend/commands/explain.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1994-5, Regents of the University of California
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.131 2005/03/25 21:57:58 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.132 2005/04/16 20:07:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -47,7 +47,7 @@ typedef struct ExplainState
4747

4848
staticvoidExplainOneQuery(Query*query,ExplainStmt*stmt,
4949
TupOutputState*tstate);
50-
staticdoubleelapsed_time(instr_time*starttime);
50+
staticdoubleelapsed_time(instr_time*starttime);
5151
staticvoidexplain_outNode(StringInfostr,
5252
Plan*plan,PlanState*planstate,
5353
Plan*outer_plan,
@@ -296,7 +296,7 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
296296
{
297297
intnt;
298298

299-
if (!rInfo->ri_TrigDesc)
299+
if (!rInfo->ri_TrigDesc|| !rInfo->ri_TrigInstrument)
300300
continue;
301301
for (nt=0;nt<rInfo->ri_TrigDesc->numtriggers;nt++)
302302
{
@@ -366,7 +366,7 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
366366

367367
/* Compute elapsed time in seconds since given timestamp */
368368
staticdouble
369-
elapsed_time(instr_time*starttime)
369+
elapsed_time(instr_time*starttime)
370370
{
371371
instr_timeendtime;
372372

@@ -663,7 +663,8 @@ explain_outNode(StringInfo str,
663663
* We have to forcibly clean up the instrumentation state because
664664
* we haven't done ExecutorEnd yet. This is pretty grotty ...
665665
*/
666-
InstrEndLoop(planstate->instrument);
666+
if (planstate->instrument)
667+
InstrEndLoop(planstate->instrument);
667668

668669
if (planstate->instrument&&planstate->instrument->nloops>0)
669670
{

‎src/backend/executor/execProcnode.c

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.48 2005/04/06 20:13:49 tgl Exp $
15+
* $PostgreSQL: pgsql/src/backend/executor/execProcnode.c,v 1.49 2005/04/16 20:07:35 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -375,6 +375,50 @@ ExecProcNode(PlanState *node)
375375
returnresult;
376376
}
377377

378+
379+
/* ----------------------------------------------------------------
380+
*MultiExecProcNode
381+
*
382+
*Execute a node that doesn't return individual tuples
383+
*(it might return a hashtable, bitmap, etc). Caller should
384+
*check it got back the expected kind of Node.
385+
*
386+
* This has essentially the same responsibilities as ExecProcNode,
387+
* but it does not do InstrStartNode/InstrStopNode (mainly because
388+
* it can't tell how many returned tuples to count). Each per-node
389+
* function must provide its own instrumentation support.
390+
* ----------------------------------------------------------------
391+
*/
392+
Node*
393+
MultiExecProcNode(PlanState*node)
394+
{
395+
Node*result;
396+
397+
CHECK_FOR_INTERRUPTS();
398+
399+
if (node->chgParam!=NULL)/* something changed */
400+
ExecReScan(node,NULL);/* let ReScan handle this */
401+
402+
switch (nodeTag(node))
403+
{
404+
/*
405+
* Only node types that actually support multiexec will be listed
406+
*/
407+
408+
caseT_HashState:
409+
result=MultiExecHash((HashState*)node);
410+
break;
411+
412+
default:
413+
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(node));
414+
result=NULL;
415+
break;
416+
}
417+
418+
returnresult;
419+
}
420+
421+
378422
/*
379423
* ExecCountSlotsNode - count up the number of tuple table slots needed
380424
*

‎src/backend/executor/instrument.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
88
*
99
* IDENTIFICATION
10-
* $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.11 2005/03/25 21:57:58 tgl Exp $
10+
* $PostgreSQL: pgsql/src/backend/executor/instrument.c,v 1.12 2005/04/16 20:07:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -33,13 +33,10 @@ InstrAlloc(int n)
3333
void
3434
InstrStartNode(Instrumentation*instr)
3535
{
36-
if (!instr)
37-
return;
38-
39-
if (!INSTR_TIME_IS_ZERO(instr->starttime))
40-
elog(DEBUG2,"InstrStartNode called twice in a row");
41-
else
36+
if (INSTR_TIME_IS_ZERO(instr->starttime))
4237
INSTR_TIME_SET_CURRENT(instr->starttime);
38+
else
39+
elog(DEBUG2,"InstrStartNode called twice in a row");
4340
}
4441

4542
/* Exit from a plan node */
@@ -48,12 +45,13 @@ InstrStopNode(Instrumentation *instr, bool returnedTuple)
4845
{
4946
instr_timeendtime;
5047

51-
if (!instr)
52-
return;
48+
/* count the returned tuples */
49+
if (returnedTuple)
50+
instr->tuplecount+=1;
5351

5452
if (INSTR_TIME_IS_ZERO(instr->starttime))
5553
{
56-
elog(DEBUG2,"InstrStopNode without start");
54+
elog(DEBUG2,"InstrStopNodecalledwithout start");
5755
return;
5856
}
5957

@@ -86,9 +84,17 @@ InstrStopNode(Instrumentation *instr, bool returnedTuple)
8684
instr->running= true;
8785
instr->firsttuple=INSTR_TIME_GET_DOUBLE(instr->counter);
8886
}
87+
}
8988

90-
if (returnedTuple)
91-
instr->tuplecount+=1;
89+
/* As above, but count multiple tuples returned at once */
90+
void
91+
InstrStopNodeMulti(Instrumentation*instr,doublenTuples)
92+
{
93+
/* count the returned tuples */
94+
instr->tuplecount+=nTuples;
95+
96+
/* delegate the rest */
97+
InstrStopNode(instr, false);
9298
}
9399

94100
/* Finish a run cycle for a plan node */
@@ -97,14 +103,14 @@ InstrEndLoop(Instrumentation *instr)
97103
{
98104
doubletotaltime;
99105

100-
if (!instr)
101-
return;
102-
103106
/* Skip if nothing has happened, or already shut down */
104107
if (!instr->running)
105108
return;
106109

107-
/* Accumulate statistics */
110+
if (!INSTR_TIME_IS_ZERO(instr->starttime))
111+
elog(DEBUG2,"InstrEndLoop called on running node");
112+
113+
/* Accumulate per-cycle statistics into totals */
108114
totaltime=INSTR_TIME_GET_DOUBLE(instr->counter);
109115

110116
instr->startup+=instr->firsttuple;

‎src/backend/executor/nodeHash.c

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,21 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.92 2005/03/31 02:02:52 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.93 2005/04/16 20:07:35 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
1515
/*
1616
* INTERFACE ROUTINES
17-
*ExecHash- generate an in-memory hash table of the relation
17+
*MultiExecHash- generate an in-memory hash table of the relation
1818
*ExecInitHash- initialize node and subnodes
1919
*ExecEndHash- shutdown node and subnodes
2020
*/
2121
#include"postgres.h"
2222

2323
#include"executor/execdebug.h"
2424
#include"executor/hashjoin.h"
25+
#include"executor/instrument.h"
2526
#include"executor/nodeHash.h"
2627
#include"executor/nodeHashjoin.h"
2728
#include"miscadmin.h"
@@ -36,12 +37,25 @@ static void ExecHashIncreaseNumBatches(HashJoinTable hashtable);
3637
/* ----------------------------------------------------------------
3738
*ExecHash
3839
*
39-
*build hash table for hashjoin, doing partitioning if more
40-
*than one batch is required.
40+
*stub for pro forma compliance
4141
* ----------------------------------------------------------------
4242
*/
4343
TupleTableSlot*
4444
ExecHash(HashState*node)
45+
{
46+
elog(ERROR,"Hash node does not support ExecProcNode call convention");
47+
returnNULL;
48+
}
49+
50+
/* ----------------------------------------------------------------
51+
*MultiExecHash
52+
*
53+
*build hash table for hashjoin, doing partitioning if more
54+
*than one batch is required.
55+
* ----------------------------------------------------------------
56+
*/
57+
Node*
58+
MultiExecHash(HashState*node)
4559
{
4660
PlanState*outerNode;
4761
List*hashkeys;
@@ -50,6 +64,10 @@ ExecHash(HashState *node)
5064
ExprContext*econtext;
5165
uint32hashvalue;
5266

67+
/* must provide our own instrumentation support */
68+
if (node->ps.instrument)
69+
InstrStartNode(node->ps.instrument);
70+
5371
/*
5472
* get state info from node
5573
*/
@@ -70,14 +88,24 @@ ExecHash(HashState *node)
7088
slot=ExecProcNode(outerNode);
7189
if (TupIsNull(slot))
7290
break;
73-
hashtable->hashNonEmpty= true;
91+
hashtable->totalTuples+=1;
7492
/* We have to compute the hash value */
7593
econtext->ecxt_innertuple=slot;
7694
hashvalue=ExecHashGetHashValue(hashtable,econtext,hashkeys);
7795
ExecHashTableInsert(hashtable,ExecFetchSlotTuple(slot),hashvalue);
7896
}
7997

80-
/* We needn't return a tuple slot or anything else */
98+
/* must provide our own instrumentation support */
99+
if (node->ps.instrument)
100+
InstrStopNodeMulti(node->ps.instrument,hashtable->totalTuples);
101+
102+
/*
103+
* We do not return the hash table directly because it's not a subtype
104+
* of Node, and so would violate the MultiExecProcNode API. Instead,
105+
* our parent Hashjoin node is expected to know how to fish it out
106+
* of our node state. Ugly but not really worth cleaning up, since
107+
* Hashjoin knows quite a bit more about Hash besides that.
108+
*/
81109
returnNULL;
82110
}
83111

@@ -220,7 +248,7 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
220248
hashtable->nbatch_original=nbatch;
221249
hashtable->nbatch_outstart=nbatch;
222250
hashtable->growEnabled= true;
223-
hashtable->hashNonEmpty=false;
251+
hashtable->totalTuples=0;
224252
hashtable->innerBatchFile=NULL;
225253
hashtable->outerBatchFile=NULL;
226254
hashtable->spaceUsed=0;

‎src/backend/executor/nodeHashjoin.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.70 2005/03/31 02:02:52 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.71 2005/04/16 20:07:35 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -123,13 +123,13 @@ ExecHashJoin(HashJoinState *node)
123123
* execute the Hash node, to build the hash table
124124
*/
125125
hashNode->hashtable=hashtable;
126-
(void)ExecProcNode((PlanState*)hashNode);
126+
(void)MultiExecProcNode((PlanState*)hashNode);
127127

128128
/*
129129
* If the inner relation is completely empty, and we're not doing
130130
* an outer join, we can quit without scanning the outer relation.
131131
*/
132-
if (!hashtable->hashNonEmpty&&node->js.jointype!=JOIN_LEFT)
132+
if (hashtable->totalTuples==0&&node->js.jointype!=JOIN_LEFT)
133133
{
134134
ExecHashTableDestroy(hashtable);
135135
node->hj_HashTable=NULL;

‎src/include/executor/executor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.117 2005/03/1621:38:09 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.118 2005/04/1620:07:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -105,6 +105,7 @@ extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
105105
*/
106106
externPlanState*ExecInitNode(Plan*node,EState*estate);
107107
externTupleTableSlot*ExecProcNode(PlanState*node);
108+
externNode*MultiExecProcNode(PlanState*node);
108109
externintExecCountSlotsNode(Plan*node);
109110
externvoidExecEndNode(PlanState*node);
110111

‎src/include/executor/hashjoin.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.35 2005/03/06 22:15:05 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/executor/hashjoin.h,v 1.36 2005/04/16 20:07:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -83,7 +83,7 @@ typedef struct HashJoinTableData
8383

8484
boolgrowEnabled;/* flag to shut off nbatch increases */
8585

86-
boolhashNonEmpty;/*did inner plan produce any rows? */
86+
doubletotalTuples;/*# tuples obtained from inner plan */
8787

8888
/*
8989
* These arrays are allocated for the life of the hash join, but

‎src/include/executor/instrument.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*
77
* Copyright (c) 2001-2005, PostgreSQL Global Development Group
88
*
9-
* $PostgreSQL: pgsql/src/include/executor/instrument.h,v 1.10 2005/03/25 21:57:59 tgl Exp $
9+
* $PostgreSQL: pgsql/src/include/executor/instrument.h,v 1.11 2005/04/16 20:07:35 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -60,9 +60,9 @@ typedef struct Instrumentation
6060
/* Info about current plan cycle: */
6161
boolrunning;/* TRUE if we've completed first tuple */
6262
instr_timestarttime;/* Start time of current iteration of node */
63-
instr_timecounter;/*Accumulates runtime for this node */
63+
instr_timecounter;/*Accumulated runtime for this node */
6464
doublefirsttuple;/* Time for first tuple of this cycle */
65-
doubletuplecount;/* Tuples so far this cycle */
65+
doubletuplecount;/* Tuplesemittedso far this cycle */
6666
/* Accumulated statistics across all completed cycles: */
6767
doublestartup;/* Total startup time (in seconds) */
6868
doubletotal;/* Total total time (in seconds) */
@@ -73,6 +73,7 @@ typedef struct Instrumentation
7373
externInstrumentation*InstrAlloc(intn);
7474
externvoidInstrStartNode(Instrumentation*instr);
7575
externvoidInstrStopNode(Instrumentation*instr,boolreturnedTuple);
76+
externvoidInstrStopNodeMulti(Instrumentation*instr,doublenTuples);
7677
externvoidInstrEndLoop(Instrumentation*instr);
7778

7879
#endif/* INSTRUMENT_H */

‎src/include/executor/nodeHash.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/executor/nodeHash.h,v 1.36 2005/03/06 22:15:05 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/executor/nodeHash.h,v 1.37 2005/04/16 20:07:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -19,6 +19,7 @@
1919
externintExecCountSlotsHash(Hash*node);
2020
externHashState*ExecInitHash(Hash*node,EState*estate);
2121
externTupleTableSlot*ExecHash(HashState*node);
22+
externNode*MultiExecHash(HashState*node);
2223
externvoidExecEndHash(HashState*node);
2324
externvoidExecReScanHash(HashState*node,ExprContext*exprCtxt);
2425

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp