8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.111 2007/02/22 22:49:27 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/executor/nodeHash.c,v 1.112 2007/06/01 17:38:44 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
31
31
#include "executor/nodeHashjoin.h"
32
32
#include "miscadmin.h"
33
33
#include "parser/parse_expr.h"
34
+ #include "utils/dynahash.h"
34
35
#include "utils/memutils.h"
35
36
#include "utils/lsyscache.h"
36
37
@@ -223,6 +224,7 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
223
224
Plan * outerNode ;
224
225
int nbuckets ;
225
226
int nbatch ;
227
+ int log2_nbuckets ;
226
228
int nkeys ;
227
229
int i ;
228
230
ListCell * ho ;
@@ -242,6 +244,10 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
242
244
printf ("nbatch = %d, nbuckets = %d\n" , nbatch , nbuckets );
243
245
#endif
244
246
247
+ /* nbuckets must be a power of 2 */
248
+ log2_nbuckets = my_log2 (nbuckets );
249
+ Assert (nbuckets == (1 << log2_nbuckets ));
250
+
245
251
/*
246
252
* Initialize the hash table control block.
247
253
*
@@ -250,6 +256,7 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
250
256
*/
251
257
hashtable = (HashJoinTable ) palloc (sizeof (HashJoinTableData ));
252
258
hashtable -> nbuckets = nbuckets ;
259
+ hashtable -> log2_nbuckets = log2_nbuckets ;
253
260
hashtable -> buckets = NULL ;
254
261
hashtable -> nbatch = nbatch ;
255
262
hashtable -> curbatch = 0 ;
@@ -345,13 +352,6 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
345
352
/* Target bucket loading (tuples per bucket) */
346
353
#define NTUP_PER_BUCKET 10
347
354
348
- /* Prime numbers that we like to use as nbuckets values */
349
- static const int hprimes [] = {
350
- 1033 , 2063 , 4111 , 8219 , 16417 , 32779 , 65539 , 131111 ,
351
- 262151 , 524341 , 1048589 , 2097211 , 4194329 , 8388619 , 16777289 , 33554473 ,
352
- 67108913 , 134217773 , 268435463 , 536870951 , 1073741831
353
- };
354
-
355
355
void
356
356
ExecChooseHashTableSize (double ntuples , int tupwidth ,
357
357
int * numbuckets ,
@@ -396,7 +396,7 @@ ExecChooseHashTableSize(double ntuples, int tupwidth,
396
396
int minbatch ;
397
397
398
398
lbuckets = (hash_table_bytes / tupsize ) / NTUP_PER_BUCKET ;
399
- lbuckets = Min (lbuckets , INT_MAX );
399
+ lbuckets = Min (lbuckets , INT_MAX / 2 );
400
400
nbuckets = (int ) lbuckets ;
401
401
402
402
dbatch = ceil (inner_rel_bytes / hash_table_bytes );
@@ -412,27 +412,22 @@ ExecChooseHashTableSize(double ntuples, int tupwidth,
412
412
double dbuckets ;
413
413
414
414
dbuckets = ceil (ntuples / NTUP_PER_BUCKET );
415
- dbuckets = Min (dbuckets , INT_MAX );
415
+ dbuckets = Min (dbuckets , INT_MAX / 2 );
416
416
nbuckets = (int ) dbuckets ;
417
417
418
418
nbatch = 1 ;
419
419
}
420
420
421
421
/*
422
- * We want nbuckets to be prime so as to avoid having bucket and batch
423
- * numbers depend on only some bits of the hash code. Choose the next
424
- * larger prime from the list in hprimes[]. (This also enforces that
425
- * nbuckets is not very small, by the simple expedient of not putting any
426
- * very small entries in hprimes[].)
422
+ * Both nbuckets and nbatch must be powers of 2 to make
423
+ * ExecHashGetBucketAndBatch fast. We already fixed nbatch; now inflate
424
+ * nbuckets to the next larger power of 2. We also force nbuckets to not
425
+ * be real small, by starting the search at 2^10.
427
426
*/
428
- for (i = 0 ; i < (int ) lengthof (hprimes ); i ++ )
429
- {
430
- if (hprimes [i ] >= nbuckets )
431
- {
432
- nbuckets = hprimes [i ];
433
- break ;
434
- }
435
- }
427
+ i = 10 ;
428
+ while ((1 << i ) < nbuckets )
429
+ i ++ ;
430
+ nbuckets = (1 << i );
436
431
437
432
* numbuckets = nbuckets ;
438
433
* numbatches = nbatch ;
@@ -765,8 +760,11 @@ ExecHashGetHashValue(HashJoinTable hashtable,
765
760
* increase. Our algorithm is
766
761
* bucketno = hashvalue MOD nbuckets
767
762
* batchno = (hashvalue DIV nbuckets) MOD nbatch
768
- * where nbuckets should preferably be prime so that all bits of the
769
- * hash value can affect both bucketno and batchno.
763
+ * where nbuckets and nbatch are both expected to be powers of 2, so we can
764
+ * do the computations by shifting and masking. (This assumes that all hash
765
+ * functions are good about randomizing all their output bits, else we are
766
+ * likely to have very skewed bucket or batch occupancy.)
767
+ *
770
768
* nbuckets doesn't change over the course of the join.
771
769
*
772
770
* nbatch is always a power of 2; we increase it only by doubling it. This
@@ -783,13 +781,13 @@ ExecHashGetBucketAndBatch(HashJoinTable hashtable,
783
781
784
782
if (nbatch > 1 )
785
783
{
786
- * bucketno = hashvalue % nbuckets ;
787
- /* since nbatch is a power of 2, can do MOD by masking */
788
- * batchno = (hashvalue / nbuckets ) & (nbatch - 1 );
784
+ /* we can do MOD by masking, DIV by shifting */
785
+ * bucketno = hashvalue & ( nbuckets - 1 );
786
+ * batchno = (hashvalue >> hashtable -> log2_nbuckets ) & (nbatch - 1 );
789
787
}
790
788
else
791
789
{
792
- * bucketno = hashvalue % nbuckets ;
790
+ * bucketno = hashvalue & ( nbuckets - 1 ) ;
793
791
* batchno = 0 ;
794
792
}
795
793
}
0 commit comments