]> granicus.if.org Git - postgresql/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:49 +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 263a0f812791f488774cec1bd69418868891670e..bae7989a4227a3c3a13d2c4d809c987c1bfb9d3d 100644 (file)
@@ -1246,7 +1246,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
@@ -1257,9 +1257,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)
@@ -1278,17 +1278,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 d2488ad988efccbb520507ba3da16a9846aa68d4..9b74ed3208c5f660132ca663b7f7a225db87f54d 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);
 }
 
 
@@ -317,9 +318,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 5d8c8b8b029aa630de955a38032c7b4efd1fa9c7..26aeaee08389b347aa67a76cd479b86c616e3d82 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);
 }
 
 /*
@@ -635,7 +636,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 152696035cd5307c32241c7e581a86ac19bdc178..d7d076758c323a571420077d1f381db4ba02f9a7 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);
        }
 
        /*