OSDN Git Service

Minor performance improvement: avoid unnecessary creation/unioning of
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 20 Apr 2005 15:48:36 +0000 (15:48 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 20 Apr 2005 15:48:36 +0000 (15:48 +0000)
bitmaps for multiple indexscans.  Instead just let each indexscan add
TIDs directly into the BitmapOr node's result bitmap.

src/backend/executor/nodeBitmapAnd.c
src/backend/executor/nodeBitmapIndexscan.c
src/backend/executor/nodeBitmapOr.c
src/include/nodes/execnodes.h

index 4af1624..1d5d94f 100644 (file)
@@ -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;
index 3ed03eb..0c802ea 100644 (file)
@@ -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
         *
index f4ef172..9078855 100644 (file)
@@ -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);
+                       }
                }
        }
 
index a5176c2..01c5074 100644 (file)
@@ -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;