diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2018-03-16 16:03:45 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2018-03-16 16:03:45 -0400 |
commit | bdc7f686d1b8f423cbd60a84cd839eca86475fd6 (patch) | |
tree | af8c09184a6b1398b7b5f171df93bea8e94f033d /src/backend/executor | |
parent | b7fbd3f4838631f7279704638caa74b974f22371 (diff) | |
download | postgresql-bdc7f686d1b8f423cbd60a84cd839eca86475fd6.tar.gz postgresql-bdc7f686d1b8f423cbd60a84cd839eca86475fd6.zip |
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
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/nodeHash.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index d10d94ccc26..75637d586a8 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -272,7 +272,8 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls) * Initialize the hash table control block. * * The hashtable control block is just palloc'd from the executor's - * per-query memory context. + * per-query memory context. Everything else should be kept inside the + * subsidiary hashCxt or batchCxt. */ hashtable = (HashJoinTable) palloc(sizeof(HashJoinTableData)); hashtable->nbuckets = nbuckets; @@ -310,6 +311,22 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls) #endif /* + * Create temporary memory contexts in which to keep the hashtable working + * storage. See notes in executor/hashjoin.h. + */ + hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext, + "HashTableContext", + ALLOCSET_DEFAULT_SIZES); + + hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt, + "HashBatchContext", + ALLOCSET_DEFAULT_SIZES); + + /* Allocate data that will live for the life of the hashjoin */ + + oldcxt = MemoryContextSwitchTo(hashtable->hashCxt); + + /* * Get info about the hash functions to be used for each hash key. Also * remember whether the join operators are strict. */ @@ -335,22 +352,6 @@ ExecHashTableCreate(Hash *node, List *hashOperators, bool keepNulls) i++; } - /* - * Create temporary memory contexts in which to keep the hashtable working - * storage. See notes in executor/hashjoin.h. - */ - hashtable->hashCxt = AllocSetContextCreate(CurrentMemoryContext, - "HashTableContext", - ALLOCSET_DEFAULT_SIZES); - - hashtable->batchCxt = AllocSetContextCreate(hashtable->hashCxt, - "HashBatchContext", - ALLOCSET_DEFAULT_SIZES); - - /* Allocate data that will live for the life of the hashjoin */ - - oldcxt = MemoryContextSwitchTo(hashtable->hashCxt); - if (nbatch > 1) { /* |