8000 Fix query-lifespan memory leakage in repeatedly executed hash joins. · postgres/postgres@5149dc9 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5149dc9

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 02c4ad3 commit 5149dc9

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
@@ -275,7 +275,8 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls)
275275
* Initialize the hash table control block.
276276
*
277277
* The hashtable control block is just palloc'd from the executor's
278-
* per-query memory context.
278+
* per-query memory context. Everything else should be kept inside the
279+
* subsidiary hashCxt or batchCxt.
279280
*/
280281
hashtable = (HashJoinTable) palloc(sizeof(HashJoinTableData));
281282
hashtable->nbuckets = nbuckets;
@@ -312,6 +313,22 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls)
312313
hashtable, nbatch, nbuckets);
313314
#endif
314315

316+
/*
317+
* Create temporary memory contexts in which to keep the hashtable working
318+
* storage. See notes in executor/hashjoin.h.
319+
*/
320+
hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext,
321+
"HashTableContext",
322+
ALLOCSET_DEFAULT_SIZES);
323+
324+
hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt,
325+
"HashBatchContext",
326+
ALLOCSET_DEFAULT_SIZES);
327+
328+
/* Allocate data that will live for the life of the hashjoin */
329+
330+
oldcxt = MemoryContextSwitchTo(hashtable->hashCxt);
331+
315332
/*
316333
* Get info about the hash functions to be used for each hash key. Also
317334
* remember whether the join operators are strict.
@@ -338,22 +355,6 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls)
338355
i++;
339356
}
340357

341-
/*
342-
* Create temporary memory contexts in which to keep the hashtable working
343-
* storage. See notes in executor/hashjoin.h.
344-
*/
345-
hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext,
346-
"HashTableContext",
347-
ALLOCSET_DEFAULT_SIZES);
348-
349< 732E code>-
hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt,
350-
"HashBatchContext",
351-
ALLOCSET_DEFAULT_SIZES);
352-
353-
/* Allocate data that will live for the life of the hashjoin */
354-
355-
oldcxt = MemoryContextSwitchTo(hashtable->hashCxt);
356-
357358
if (nbatch > 1)
358359
{
359360
/*

0 commit comments

Comments
 (0)
0