Commit 9d646321 authored by Tom Lane's avatar Tom Lane

Minor performance improvement: avoid unnecessary creation/unioning of

bitmaps for multiple indexscans.  Instead just let each indexscan add
TIDs directly into the BitmapOr node's result bitmap.
parent de4fbfad
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapAnd.c,v 1.1 2005/04/19 22:35:12 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapAnd.c,v 1.2 2005/04/20 15:48:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -46,6 +46,7 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate) ...@@ -46,6 +46,7 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate)
PlanState **bitmapplanstates; PlanState **bitmapplanstates;
int nplans; int nplans;
int i; int i;
ListCell *l;
Plan *initNode; Plan *initNode;
CXT1_printf("ExecInitBitmapAnd: context is %d\n", CurrentMemoryContext); CXT1_printf("ExecInitBitmapAnd: context is %d\n", CurrentMemoryContext);
...@@ -78,10 +79,12 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate) ...@@ -78,10 +79,12 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate)
* call ExecInitNode on each of the plans to be executed and save the * call ExecInitNode on each of the plans to be executed and save the
* results into the array "bitmapplanstates". * results into the array "bitmapplanstates".
*/ */
for (i = 0; i < nplans; i++) i = 0;
foreach(l, node->bitmapplans)
{ {
initNode = (Plan *) list_nth(node->bitmapplans, i); initNode = (Plan *) lfirst(l);
bitmapplanstates[i] = ExecInitNode(initNode, estate); bitmapplanstates[i] = ExecInitNode(initNode, estate);
i++;
} }
return bitmapandstate; return bitmapandstate;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.1 2005/04/19 22:35:12 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.2 2005/04/20 15:48:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -63,9 +63,21 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node) ...@@ -63,9 +63,21 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node)
scandesc = node->biss_ScanDesc; scandesc = node->biss_ScanDesc;
/* /*
* Prepare result bitmap * Prepare the result bitmap. Normally we just create a new one to pass
* back; however, our parent node is allowed to store a pre-made one
* into node->biss_result, in which case we just OR our tuple IDs into
* the existing bitmap. (This saves needing explicit UNION steps.)
*/ */
tbm = tbm_create(work_mem * 1024L); if (node->biss_result)
{
tbm = node->biss_result;
node->biss_result = NULL; /* reset for next time */
}
else
{
/* XXX should we use less than work_mem for this? */
tbm = tbm_create(work_mem * 1024L);
}
/* /*
* Get TIDs from index and insert into bitmap * Get TIDs from index and insert into bitmap
...@@ -271,6 +283,9 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate) ...@@ -271,6 +283,9 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
indexstate->ss.ps.plan = (Plan *) node; indexstate->ss.ps.plan = (Plan *) node;
indexstate->ss.ps.state = estate; indexstate->ss.ps.state = estate;
/* normally we don't make the result bitmap till runtime */
indexstate->biss_result = NULL;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
* *
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/nodeBitmapOr.c,v 1.1 2005/04/19 22:35:12 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapOr.c,v 1.2 2005/04/20 15:48:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "executor/execdebug.h" #include "executor/execdebug.h"
#include "executor/instrument.h" #include "executor/instrument.h"
#include "executor/nodeBitmapOr.h" #include "executor/nodeBitmapOr.h"
#include "miscadmin.h"
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -46,6 +47,7 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate) ...@@ -46,6 +47,7 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate)
PlanState **bitmapplanstates; PlanState **bitmapplanstates;
int nplans; int nplans;
int i; int i;
ListCell *l;
Plan *initNode; Plan *initNode;
CXT1_printf("ExecInitBitmapOr: context is %d\n", CurrentMemoryContext); CXT1_printf("ExecInitBitmapOr: context is %d\n", CurrentMemoryContext);
...@@ -78,10 +80,12 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate) ...@@ -78,10 +80,12 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate)
* call ExecInitNode on each of the plans to be executed and save the * call ExecInitNode on each of the plans to be executed and save the
* results into the array "bitmapplanstates". * results into the array "bitmapplanstates".
*/ */
for (i = 0; i < nplans; i++) i = 0;
foreach(l, node->bitmapplans)
{ {
initNode = (Plan *) list_nth(node->bitmapplans, i); initNode = (Plan *) lfirst(l);
bitmapplanstates[i] = ExecInitNode(initNode, estate); bitmapplanstates[i] = ExecInitNode(initNode, estate);
i++;
} }
return bitmaporstate; return bitmaporstate;
...@@ -128,17 +132,41 @@ MultiExecBitmapOr(BitmapOrState *node) ...@@ -128,17 +132,41 @@ MultiExecBitmapOr(BitmapOrState *node)
PlanState *subnode = bitmapplans[i]; PlanState *subnode = bitmapplans[i];
TIDBitmap *subresult; TIDBitmap *subresult;
subresult = (TIDBitmap *) MultiExecProcNode(subnode); /*
* We can special-case BitmapIndexScan children to avoid an
* explicit tbm_union step for each child: just pass down the
* current result bitmap and let the child OR directly into it.
*/
if (IsA(subnode, BitmapIndexScanState))
{
if (result == NULL) /* first subplan */
{
/* XXX should we use less than work_mem for this? */
result = tbm_create(work_mem * 1024L);
}
((BitmapIndexScanState *) subnode)->biss_result = result;
if (!subresult || !IsA(subresult, TIDBitmap)) subresult = (TIDBitmap *) MultiExecProcNode(subnode);
elog(ERROR, "unrecognized result from subplan");
if (result == NULL) if (subresult != result)
result = subresult; /* first subplan */ elog(ERROR, "unrecognized result from subplan");
}
else else
{ {
tbm_union(result, subresult); /* standard implementation */
tbm_free(subresult); subresult = (TIDBitmap *) MultiExecProcNode(subnode);
if (!subresult || !IsA(subresult, TIDBitmap))
elog(ERROR, "unrecognized result from subplan");
if (result == NULL)
result = subresult; /* first subplan */
else
{
tbm_union(result, subresult);
tbm_free(subresult);
}
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.126 2005/04/19 22:35:17 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.127 2005/04/20 15:48:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -901,6 +901,7 @@ typedef struct IndexScanState ...@@ -901,6 +901,7 @@ typedef struct IndexScanState
/* ---------------- /* ----------------
* BitmapIndexScanState information * BitmapIndexScanState information
* *
* result bitmap to return output into, or NULL
* ScanKeys Skey structures to scan index rel * ScanKeys Skey structures to scan index rel
* NumScanKeys number of Skey structs * NumScanKeys number of Skey structs
* RuntimeKeyInfo array of exprstates for Skeys * RuntimeKeyInfo array of exprstates for Skeys
...@@ -914,6 +915,7 @@ typedef struct IndexScanState ...@@ -914,6 +915,7 @@ typedef struct IndexScanState
typedef struct BitmapIndexScanState typedef struct BitmapIndexScanState
{ {
ScanState ss; /* its first field is NodeTag */ ScanState ss; /* its first field is NodeTag */
TIDBitmap *biss_result;
ScanKey biss_ScanKeys; ScanKey biss_ScanKeys;
int biss_NumScanKeys; int biss_NumScanKeys;
ExprState **biss_RuntimeKeyInfo; ExprState **biss_RuntimeKeyInfo;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment