Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit bdc7f68

Browse files
committed
Fix query-lifespan memory leakage in repeatedly executed hash joins.
ExecHashTableCreate allocated some memory that wasn't freed by ExecHashTableDestroy, specifically the per-hash-key function information. That's not a huge amount of data, but if one runs a query that repeats a hash join enough times, it builds up. Fix by arranging for the data in question to be kept in the hashtable's hashCxt instead of leaving it "loose" in the query-lifespan executor context. (This ensures that we'll also clean up anything that the hash functions allocate in fn_mcxt.) Per report from Amit Khandekar. It's been like this forever, so back-patch to all supported branches. Discussion: https://postgr.es/m/CAJ3gD9cFofAWGvcxLOxDHC=B0hjtW8yGmUsF2hdGh97CM38=7g@mail.gmail.com
1 parent b7fbd3f commit bdc7f68

File tree

1 file changed

+18
-17
lines changed

1 file changed

+18
-17
lines changed

src/backend/executor/nodeHash.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,8 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls)
272272
* Initialize the hash table control block.
273273
*
274274
* The hashtable control block is just palloc'd from the executor's
275-
* per-query memory context.
275+
* per-query memory context. Everything else should be kept inside the
276+
* subsidiary hashCxt or batchCxt.
276277
*/
277278
hashtable = (HashJoinTable) palloc(sizeof(HashJoinTableData));
278279
hashtable->nbuckets = nbuckets;
@@ -309,6 +310,22 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls)
309310
hashtable, nbatch, nbuckets);
310311
#endif
311312

313+
/*
314+
* Create temporary memory contexts in which to keep the hashtable working
315+
* storage. See notes in executor/hashjoin.h.
316+
*/
317+
hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext,
318+
"HashTableContext",
319+
ALLOCSET_DEFAULT_SIZES);
320+
321+
hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt,
322+
"HashBatchContext",
323+
ALLOCSET_DEFAULT_SIZES);
324+
325+
/* Allocate data that will live for the life of the hashjoin */
326+
327+
oldcxt = MemoryContextSwitchTo(hashtable->hashCxt);
328+
312329
/*
313330
* Get info about the hash functions to be used for each hash key. Also
314331
* remember whether the join operators are strict.
@@ -335,22 +352,6 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls)
335352
i++;
336353
}
337354

338-
/*
339-
* Create temporary memory contexts in which to keep the hashtable working
340-
* storage. See notes in executor/hashjoin.h.
341-
*/
342-
hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext,
343-
"HashTableContext",
344-
ALLOCSET_DEFAULT_SIZES);
345-
346-
hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt,
347-
"HashBatchContext",
348-
ALLOCSET_DEFAULT_SIZES);
349-
350-
/* Allocate data that will live for the life of the hashjoin */
351-
352-
oldcxt = MemoryContextSwitchTo(hashtable->hashCxt);
353-
354355
if (nbatch > 1)
355356
{
356357
/*

0 commit comments

Comments
 (0)