From: Tom Lane Date: Wed, 20 Apr 2005 15:48:36 +0000 (+0000) Subject: Minor performance improvement: avoid unnecessary creation/unioning of X-Git-Tag: REL9_0_0~10377 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=9d64632144034cd6b0a32bad1c3a305008149754;p=pg-rex%2Fsyncrep.git 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. --- diff --git a/src/backend/executor/nodeBitmapAnd.c b/src/backend/executor/nodeBitmapAnd.c index 4af1624012..1d5d94fc3f 100644 --- a/src/backend/executor/nodeBitmapAnd.c +++ b/src/backend/executor/nodeBitmapAnd.c @@ -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; diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c index 3ed03eb7cb..0c802ea49b 100644 --- a/src/backend/executor/nodeBitmapIndexscan.c +++ b/src/backend/executor/nodeBitmapIndexscan.c @@ -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.) */ - 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 @@ -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 * diff --git a/src/backend/executor/nodeBitmapOr.c b/src/backend/executor/nodeBitmapOr.c index f4ef17223c..9078855ec3 100644 --- a/src/backend/executor/nodeBitmapOr.c +++ b/src/backend/executor/nodeBitmapOr.c @@ -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,17 +132,41 @@ MultiExecBitmapOr(BitmapOrState *node) PlanState *subnode = bitmapplans[i]; 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)) - elog(ERROR, "unrecognized result from subplan"); + subresult = (TIDBitmap *) MultiExecProcNode(subnode); - if (result == NULL) - result = subresult; /* first subplan */ + if (subresult != result) + elog(ERROR, "unrecognized result from subplan"); + } else { - tbm_union(result, subresult); - tbm_free(subresult); + /* standard implementation */ + 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); + } } } diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index a5176c2f95..01c5074762 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -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;