diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index a47dc328c4b07504489f9bf55e887dd5beaa839f..5e05ec3df37011fbeb2859310e638c1be8513385 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);