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.
This commit is contained in:
parent
de4fbfadc5
commit
9d64632144
@ -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)
|
|||||||
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)
|
|||||||
* 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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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)
|
|||||||
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.)
|
||||||
*/
|
*/
|
||||||
|
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);
|
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)
|
|||||||
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 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* 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 @@
|
|||||||
#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)
|
|||||||
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)
|
|||||||
* 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,6 +132,29 @@ MultiExecBitmapOr(BitmapOrState *node)
|
|||||||
PlanState *subnode = bitmapplans[i];
|
PlanState *subnode = bitmapplans[i];
|
||||||
TIDBitmap *subresult;
|
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);
|
subresult = (TIDBitmap *) MultiExecProcNode(subnode);
|
||||||
|
|
||||||
if (!subresult || !IsA(subresult, TIDBitmap))
|
if (!subresult || !IsA(subresult, TIDBitmap))
|
||||||
@ -141,6 +168,7 @@ MultiExecBitmapOr(BitmapOrState *node)
|
|||||||
tbm_free(subresult);
|
tbm_free(subresult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* We could return an empty result set here? */
|
/* We could return an empty result set here? */
|
||||||
if (result == NULL)
|
if (result == NULL)
|
||||||
|
@ -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
|
|||||||
/* ----------------
|
/* ----------------
|
||||||
* 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
|
|||||||
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user