aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2015-10-04 15:55:07 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2015-10-04 15:55:07 -0400
commite5c94c7bbcf091617f0720a3ccbe898cd8beff17 (patch)
treef511978d7466c88e5f1bb1ef4a46ec8e695c6dbd
parentca5b42d85486f814b3b510e436157f443fd73683 (diff)
downloadpostgresql-e5c94c7bbcf091617f0720a3ccbe898cd8beff17.tar.gz
postgresql-e5c94c7bbcf091617f0720a3ccbe898cd8beff17.zip
Further twiddling of nodeHash.c hashtable sizing calculation.
On reflection, the submitted patch didn't really work to prevent the request size from exceeding MaxAllocSize, because of the fact that we'd happily round nbuckets up to the next power of 2 after we'd limited it to max_pointers. The simplest way to enforce the limit correctly is to round max_pointers down to a power of 2 when it isn't one already. (Note that the constraint to INT_MAX / 2, if it were doing anything useful at all, is properly applied after that.)
-rw-r--r--src/backend/executor/nodeHash.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index a47dc328c4b..5e05ec3df37 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -415,6 +415,7 @@ ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
long hash_table_bytes;
long skew_table_bytes;
long max_pointers;
+ long mppow2;
int nbatch = 1;
int nbuckets;
double dbuckets;
@@ -485,14 +486,20 @@ ExecChooseHashTableSize(double ntuples, int tupwidth, bool useskew,
*/
max_pointers = (work_mem * 1024L) / sizeof(HashJoinTuple);
max_pointers = Min(max_pointers, MaxAllocSize / sizeof(HashJoinTuple));
- /* also ensure we avoid integer overflow in nbatch and nbuckets */
+ /* If max_pointers isn't a power of 2, must round it down to one */
+ mppow2 = 1L << my_log2(max_pointers);
+ if (max_pointers != mppow2)
+ max_pointers = mppow2 / 2;
+
+ /* Also ensure we avoid integer overflow in nbatch and nbuckets */
/* (this step is redundant given the current value of MaxAllocSize) */
max_pointers = Min(max_pointers, INT_MAX / 2);
dbuckets = ceil(ntuples / NTUP_PER_BUCKET);
dbuckets = Min(dbuckets, max_pointers);
+ nbuckets = (int) dbuckets;
/* don't let nbuckets be really small, though ... */
- nbuckets = Max((int) dbuckets, 1024);
+ nbuckets = Max(nbuckets, 1024);
/* ... and force it to be a power of 2. */
nbuckets = 1 << my_log2(nbuckets);