]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Reset, not recreate, execGrouping.c style hashtables.
authorAndres Freund <andres@anarazel.de>
Sat, 9 Feb 2019 08:35:57 +0000 (00:35 -0800)
committerAndres Freund <andres@anarazel.de>
Sat, 9 Feb 2019 09:05:50 +0000 (01:05 -0800)
This uses the facility added in the preceding commit to fix
performance issues caused by rebuilding the hashtable (with its
comparator expression being the most expensive bit), after every
reset. That's especially important when the comparator is JIT
compiled.

Bug: #15592 #15486
Reported-By: Jakub Janeček, Dmitry Marakasov
Author: Andres Freund
Discussion:
    https://postgr.es/m/15486-05850f065da42931@postgresql.org
    https://postgr.es/m/20190114180423.ywhdg2iagzvh43we@alap3.anarazel.de
Backpatch: 11, where I broke this in bf6c614a2f2c5

src/backend/executor/nodeAgg.c
src/backend/executor/nodeRecursiveunion.c
src/backend/executor/nodeSetOp.c
src/backend/executor/nodeSubplan.c

index 0fe0c22c1ea4365cb79038c64f86fe1fcc9651fb..af93b4db6c038cb8a271bcb4e85021aac9a8bfcc 100644 (file)
@@ -1245,7 +1245,7 @@ find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
 }
 
 /*
- * Initialize the hash table(s) to empty.
+ * (Re-)initialize the hash table(s) to empty.
  *
  * To implement hashed aggregation, we need a hashtable that stores a
  * representative tuple and an array of AggStatePerGroup structs for each
@@ -1256,9 +1256,9 @@ find_unaggregated_cols_walker(Node *node, Bitmapset **colnos)
  * We have a separate hashtable and associated perhash data structure for each
  * grouping set for which we're doing hashing.
  *
- * The hash tables always live in the hashcontext's per-tuple memory context
- * (there is only one of these for all tables together, since they are all
- * reset at the same time).
+ * The contents of the hash tables always live in the hashcontext's per-tuple
+ * memory context (there is only one of these for all tables together, since
+ * they are all reset at the same time).
  */
 static void
 build_hash_table(AggState *aggstate)
@@ -1277,17 +1277,21 @@ build_hash_table(AggState *aggstate)
 
                Assert(perhash->aggnode->numGroups > 0);
 
-               perhash->hashtable = BuildTupleHashTable(&aggstate->ss.ps,
-                                                                                                perhash->hashslot->tts_tupleDescriptor,
-                                                                                                perhash->numCols,
-                                                                                                perhash->hashGrpColIdxHash,
-                                                                                                perhash->eqfuncoids,
-                                                                                                perhash->hashfunctions,
-                                                                                                perhash->aggnode->numGroups,
-                                                                                                additionalsize,
-                                                                                                aggstate->hashcontext->ecxt_per_tuple_memory,
-                                                                                                tmpmem,
-                                                                                                DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit));
+               if (perhash->hashtable)
+                       ResetTupleHashTable(perhash->hashtable);
+               else
+                       perhash->hashtable = BuildTupleHashTableExt(&aggstate->ss.ps,
+                                                                                                               perhash->hashslot->tts_tupleDescriptor,
+                                                                                                               perhash->numCols,
+                                                                                                               perhash->hashGrpColIdxHash,
+                                                                                                               perhash->eqfuncoids,
+                                                                                                               perhash->hashfunctions,
+                                                                                                               perhash->aggnode->numGroups,
+                                                                                                               additionalsize,
+                                                                                                               aggstate->ss.ps.state->es_query_cxt,
+                                                                                                               aggstate->hashcontext->ecxt_per_tuple_memory,
+                                                                                                               tmpmem,
+                                                                                                               DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit));
        }
 }
 
index 6b3ea5afb31946d133200c70cfc80b3a2b37e978..791f1d6fd23af7bcf9916e61ac376875cfc508e3 100644 (file)
@@ -37,17 +37,18 @@ build_hash_table(RecursiveUnionState *rustate)
        Assert(node->numCols > 0);
        Assert(node->numGroups > 0);
 
-       rustate->hashtable = BuildTupleHashTable(&rustate->ps,
-                                                                                        desc,
-                                                                                        node->numCols,
-                                                                                        node->dupColIdx,
-                                                                                        rustate->eqfuncoids,
-                                                                                        rustate->hashfunctions,
-                                                                                        node->numGroups,
-                                                                                        0,
-                                                                                        rustate->tableContext,
-                                                                                        rustate->tempContext,
-                                                                                        false);
+       rustate->hashtable = BuildTupleHashTableExt(&rustate->ps,
+                                                                                               desc,
+                                                                                               node->numCols,
+                                                                                               node->dupColIdx,
+                                                                                               rustate->eqfuncoids,
+                                                                                               rustate->hashfunctions,
+                                                                                               node->numGroups,
+                                                                                               0,
+                                                                                               rustate->ps.state->es_query_cxt,
+                                                                                               rustate->tableContext,
+                                                                                               rustate->tempContext,
+                                                                                               false);
 }
 
 
@@ -322,9 +323,9 @@ ExecReScanRecursiveUnion(RecursiveUnionState *node)
        if (node->tableContext)
                MemoryContextResetAndDeleteChildren(node->tableContext);
 
-       /* And rebuild empty hashtable if needed */
+       /* Empty hashtable if needed */
        if (plan->numCols > 0)
-               build_hash_table(node);
+               ResetTupleHashTable(node->hashtable);
 
        /* reset processing state */
        node->recursing = false;
index 3fa4a5fcc6554ccb328d48b901bdc155f8fcd196..d978a7c255faafbc103bc7dca37f2a90f70ffeff 100644 (file)
@@ -126,17 +126,18 @@ build_hash_table(SetOpState *setopstate)
        Assert(node->strategy == SETOP_HASHED);
        Assert(node->numGroups > 0);
 
-       setopstate->hashtable = BuildTupleHashTable(&setopstate->ps,
-                                                                                               desc,
-                                                                                               node->numCols,
-                                                                                               node->dupColIdx,
-                                                                                               setopstate->eqfuncoids,
-                                                                                               setopstate->hashfunctions,
-                                                                                               node->numGroups,
-                                                                                               0,
-                                                                                               setopstate->tableContext,
-                                                                                               econtext->ecxt_per_tuple_memory,
-                                                                                               false);
+       setopstate->hashtable = BuildTupleHashTableExt(&setopstate->ps,
+                                                                                                  desc,
+                                                                                                  node->numCols,
+                                                                                                  node->dupColIdx,
+                                                                                                  setopstate->eqfuncoids,
+                                                                                                  setopstate->hashfunctions,
+                                                                                                  node->numGroups,
+                                                                                                  0,
+                                                                                                  setopstate->ps.state->es_query_cxt,
+                                                                                                  setopstate->tableContext,
+                                                                                                  econtext->ecxt_per_tuple_memory,
+                                                                                                  false);
 }
 
 /*
@@ -634,7 +635,7 @@ ExecReScanSetOp(SetOpState *node)
        /* And rebuild empty hashtable if needed */
        if (((SetOp *) node->ps.plan)->strategy == SETOP_HASHED)
        {
-               build_hash_table(node);
+               ResetTupleHashTable(node->hashtable);
                node->table_filled = false;
        }
 
index 63de981034d544a5e3a13cc19d7dce8686607034..9564d54ed4c1539d23b7ad4cf00b8c0e1d5dfb31 100644 (file)
@@ -481,8 +481,8 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
        Assert(subplan->subLinkType == ANY_SUBLINK);
 
        /*
-        * If we already had any hash tables, destroy 'em; then create empty hash
-        * table(s).
+        * If we already had any hash tables, reset 'em; otherwise create empty
+        * hash table(s).
         *
         * If we need to distinguish accurately between FALSE and UNKNOWN (i.e.,
         * NULL) results of the IN operation, then we have to store subplan output
@@ -505,17 +505,21 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
        if (nbuckets < 1)
                nbuckets = 1;
 
-       node->hashtable = BuildTupleHashTable(node->parent,
-                                                                                 node->descRight,
-                                                                                 ncols,
-                                                                                 node->keyColIdx,
-                                                                                 node->tab_eq_funcoids,
-                                                                                 node->tab_hash_funcs,
-                                                                                 nbuckets,
-                                                                                 0,
-                                                                                 node->hashtablecxt,
-                                                                                 node->hashtempcxt,
-                                                                                 false);
+       if (node->hashtable)
+               ResetTupleHashTable(node->hashtable);
+       else
+               node->hashtable = BuildTupleHashTableExt(node->parent,
+                                                                                                node->descRight,
+                                                                                                ncols,
+                                                                                                node->keyColIdx,
+                                                                                                node->tab_eq_funcoids,
+                                                                                                node->tab_hash_funcs,
+                                                                                                nbuckets,
+                                                                                                0,
+                                                                                                node->planstate->state->es_query_cxt,
+                                                                                                node->hashtablecxt,
+                                                                                                node->hashtempcxt,
+                                                                                                false);
 
        if (!subplan->unknownEqFalse)
        {
@@ -527,17 +531,22 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
                        if (nbuckets < 1)
                                nbuckets = 1;
                }
-               node->hashnulls = BuildTupleHashTable(node->parent,
-                                                                                         node->descRight,
-                                                                                         ncols,
-                                                                                         node->keyColIdx,
-                                                                                         node->tab_eq_funcoids,
-                                                                                         node->tab_hash_funcs,
-                                                                                         nbuckets,
-                                                                                         0,
-                                                                                         node->hashtablecxt,
-                                                                                         node->hashtempcxt,
-                                                                                         false);
+
+               if (node->hashnulls)
+                       ResetTupleHashTable(node->hashtable);
+               else
+                       node->hashnulls = BuildTupleHashTableExt(node->parent,
+                                                                                                        node->descRight,
+                                                                                                        ncols,
+                                                                                                        node->keyColIdx,
+                                                                                                        node->tab_eq_funcoids,
+                                                                                                        node->tab_hash_funcs,
+                                                                                                        nbuckets,
+                                                                                                        0,
+                                                                                                        node->planstate->state->es_query_cxt,
+                                                                                                        node->hashtablecxt,
+                                                                                                        node->hashtempcxt,
+                                                                                                        false);
        }
 
        /*