Skip to content
Snippets Groups Projects
Commit 9d646321 authored by Tom Lane's avatar Tom Lane
Browse files

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
No related branches found
No related tags found
No related merge requests found
......@@ -8,7 +8,7 @@
*
*
* 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)
PlanState **bitmapplanstates;
int nplans;
int i;
ListCell *l;
Plan *initNode;
CXT1_printf("ExecInitBitmapAnd: context is %d\n", CurrentMemoryContext);
......@@ -78,10 +79,12 @@ ExecInitBitmapAnd(BitmapAnd *node, EState *estate)
* call ExecInitNode on each of the plans to be executed and save the
* 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);
i++;
}
return bitmapandstate;
......
......@@ -8,7 +8,7 @@
*
*
* 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)
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.)
*/
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
......@@ -271,6 +283,9 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate)
indexstate->ss.ps.plan = (Plan *) node;
indexstate->ss.ps.state = estate;
/* normally we don't make the result bitmap till runtime */
indexstate->biss_result = NULL;
/*
* Miscellaneous initialization
*
......
......@@ -8,7 +8,7 @@
*
*
* 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 @@
#include "executor/execdebug.h"
#include "executor/instrument.h"
#include "executor/nodeBitmapOr.h"
#include "miscadmin.h"
/* ----------------------------------------------------------------
......@@ -46,6 +47,7 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate)
PlanState **bitmapplanstates;
int nplans;
int i;
ListCell *l;
Plan *initNode;
CXT1_printf("ExecInitBitmapOr: context is %d\n", CurrentMemoryContext);
......@@ -78,10 +80,12 @@ ExecInitBitmapOr(BitmapOr *node, EState *estate)
* call ExecInitNode on each of the plans to be executed and save the
* 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);
i++;
}
return bitmaporstate;
......@@ -128,6 +132,29 @@ MultiExecBitmapOr(BitmapOrState *node)
PlanState *subnode = bitmapplans[i];
TIDBitmap *subresult;
/*
* 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;
subresult = (TIDBitmap *) MultiExecProcNode(subnode);
if (subresult != result)
elog(ERROR, "unrecognized result from subplan");
}
else
{
/* standard implementation */
subresult = (TIDBitmap *) MultiExecProcNode(subnode);
if (!subresult || !IsA(subresult, TIDBitmap))
......@@ -141,6 +168,7 @@ MultiExecBitmapOr(BitmapOrState *node)
tbm_free(subresult);
}
}
}
/* We could return an empty result set here? */
if (result == NULL)
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* 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
/* ----------------
* BitmapIndexScanState information
*
* result bitmap to return output into, or NULL
* ScanKeys Skey structures to scan index rel
* NumScanKeys number of Skey structs
* RuntimeKeyInfo array of exprstates for Skeys
......@@ -914,6 +915,7 @@ typedef struct IndexScanState
typedef struct BitmapIndexScanState
{
ScanState ss; /* its first field is NodeTag */
TIDBitmap *biss_result;
ScanKey biss_ScanKeys;
int biss_NumScanKeys;
ExprState **biss_RuntimeKeyInfo;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment