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

Commit 9e17bdb

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 013c0ba commit 9e17bdb

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
@@ -472,7 +472,8 @@ ExecHashTableCreate(HashState *state, List *hashOperators, bool keepNulls)
472472
* Initialize the hash table control block.
473473
*
474474
* The hashtable control block is just palloc'd from the executor's
475-
* per-query memory context.
475+
* per-query memory context. Everything else should be kept inside the
476+
* subsidiary hashCxt or batchCxt.
476477
*/
477478
hashtable = (HashJoinTable) palloc(sizeof(HashJoinTableData));
478479
hashtable->nbuckets = nbuckets;
@@ -514,6 +515,22 @@ ExecHashTableCreate(HashState *state, List *hashOperators, bool keepNulls)
514515
hashtable, nbatch, nbuckets);
515516
#endif
516517

518+
/*
519+
* Create temporary memory contexts in which to keep the hashtable working
520+
* storage. See notes in executor/hashjoin.h.
521+
*/
522+
hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext,
523+
"HashTableContext",
524+
ALLOCSET_DEFAULT_SIZES);
525+
526+
hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt,
527+
"HashBatchContext",
528+
ALLOCSET_DEFAULT_SIZES);
529+
530+
/* Allocate data that will live for the life of the hashjoin */
531+
532+
oldcxt = MemoryContextSwitchTo(hashtable->hashCxt);
533+
517534
/*
518535
* Get info about the hash functions to be used for each hash key. Also
519536
* remember whether the join operators are strict.
@@ -540,22 +557,6 @@ ExecHashTableCreate(HashState *state, List *hashOperators, bool keepNulls)
540557
i++;
541558
}
542559

543-
/*
544-
* Create temporary memory contexts in which to keep the hashtable working
545-
* storage. See notes in executor/hashjoin.h.
546-
*/
547-
hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext,
548-
"HashTableContext",
549-
ALLOCSET_DEFAULT_SIZES);
550-
551-
hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt,
552-
"HashBatchContext",
553-
ALLOCSET_DEFAULT_SIZES);
554-
555-
/* Allocate data that will live for the life of the hashjoin */
556-
557-
oldcxt = MemoryContextSwitchTo(hashtable->hashCxt);
558-
559560
if (nbatch > 1 && hashtable->parallel_state == NULL)
560561
{
561562
/*

0 commit comments

Comments
 (0)