88 *
99 *
1010 * 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 $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
3131#include "executor/nodeHashjoin.h"
3232#include "miscadmin.h"
3333#include "parser/parse_expr.h"
34+ #include "utils/dynahash.h"
3435#include "utils/memutils.h"
3536#include "utils/lsyscache.h"
3637
@@ -223,6 +224,7 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
223224Plan * outerNode ;
224225int nbuckets ;
225226int nbatch ;
227+ int log2_nbuckets ;
226228int nkeys ;
227229int i ;
228230ListCell * ho ;
@@ -242,6 +244,10 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
242244printf ("nbatch = %d, nbuckets = %d\n" ,nbatch ,nbuckets );
243245#endif
244246
247+ /* nbuckets must be a power of 2 */
248+ log2_nbuckets = my_log2 (nbuckets );
249+ Assert (nbuckets == (1 <<log2_nbuckets ));
250+
245251/*
246252 * Initialize the hash table control block.
247253 *
@@ -250,6 +256,7 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
250256 */
251257hashtable = (HashJoinTable )palloc (sizeof (HashJoinTableData ));
252258hashtable -> nbuckets = nbuckets ;
259+ hashtable -> log2_nbuckets = log2_nbuckets ;
253260hashtable -> buckets = NULL ;
254261hashtable -> nbatch = nbatch ;
255262hashtable -> curbatch = 0 ;
@@ -345,13 +352,6 @@ ExecHashTableCreate(Hash *node, List *hashOperators)
345352/* Target bucket loading (tuples per bucket) */
346353#define NTUP_PER_BUCKET 10
347354
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-
355355void
356356ExecChooseHashTableSize (double ntuples ,int tupwidth ,
357357int * numbuckets ,
@@ -396,7 +396,7 @@ ExecChooseHashTableSize(double ntuples, int tupwidth,
396396int minbatch ;
397397
398398lbuckets = (hash_table_bytes /tupsize ) /NTUP_PER_BUCKET ;
399- lbuckets = Min (lbuckets ,INT_MAX );
399+ lbuckets = Min (lbuckets ,INT_MAX / 2 );
400400nbuckets = (int )lbuckets ;
401401
402402dbatch = ceil (inner_rel_bytes /hash_table_bytes );
@@ -412,27 +412,22 @@ ExecChooseHashTableSize(double ntuples, int tupwidth,
412412double dbuckets ;
413413
414414dbuckets = ceil (ntuples /NTUP_PER_BUCKET );
415- dbuckets = Min (dbuckets ,INT_MAX );
415+ dbuckets = Min (dbuckets ,INT_MAX / 2 );
416416nbuckets = (int )dbuckets ;
417417
418418nbatch = 1 ;
419419}
420420
421421/*
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.
427426 */
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 );
436431
437432* numbuckets = nbuckets ;
438433* numbatches = nbatch ;
@@ -765,8 +760,11 @@ ExecHashGetHashValue(HashJoinTable hashtable,
765760 * increase. Our algorithm is
766761 *bucketno = hashvalue MOD nbuckets
767762 *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+ *
770768 * nbuckets doesn't change over the course of the join.
771769 *
772770 * nbatch is always a power of 2; we increase it only by doubling it. This
@@ -783,13 +781,13 @@ ExecHashGetBucketAndBatch(HashJoinTable hashtable,
783781
784782if (nbatch > 1 )
785783{
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 );
789787}
790788else
791789{
792- * bucketno = hashvalue % nbuckets ;
790+ * bucketno = hashvalue & ( nbuckets - 1 ) ;
793791* batchno = 0 ;
794792}
795793}