88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.72 2008/01/01 19:45:46 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.73 2008/03/15 20:46:31 tgl Exp $
1212 *
1313 * NOTES
1414 * Postgres hash pages look like ordinary relation pages. The opaque
@@ -312,15 +312,17 @@ _hash_chgbufaccess(Relation rel,
312312
313313/*
314314 *_hash_metapinit() -- Initialize the metadata page of a hash index,
315- *the two buckets that we begin with and the initial
316- *bitmap page.
315+ *the initial buckets, and the initial bitmap page.
316+ *
317+ * The initial number of buckets is dependent on num_tuples, an estimate
318+ * of the number of tuples to be loaded into the index initially.
317319 *
318320 * We are fairly cavalier about locking here, since we know that no one else
319321 * could be accessing this index. In particular the rule about not holding
320322 * multiple buffer locks is ignored.
321323 */
322324void
323- _hash_metapinit (Relation rel )
325+ _hash_metapinit (Relation rel , double num_tuples )
324326{
325327HashMetaPage metap ;
326328HashPageOpaque pageopaque ;
@@ -330,7 +332,10 @@ _hash_metapinit(Relation rel)
330332int32 data_width ;
331333int32 item_width ;
332334int32 ffactor ;
333- uint16 i ;
335+ double dnumbuckets ;
336+ uint32 num_buckets ;
337+ uint32 log2_num_buckets ;
338+ uint32 i ;
334339
335340/* safety check */
336341if (RelationGetNumberOfBlocks (rel )!= 0 )
@@ -354,7 +359,26 @@ _hash_metapinit(Relation rel)
354359ffactor = 10 ;
355360
356361/*
357- * We initialize the metapage, the first two bucket pages, and the first
362+ * Choose the number of initial bucket pages to match the fill factor
363+ * given the estimated number of tuples. We round up the result to the
364+ * next power of 2, however, and always force at least 2 bucket pages.
365+ * The upper limit is determined by considerations explained in
366+ * _hash_expandtable().
367+ */
368+ dnumbuckets = num_tuples /ffactor ;
369+ if (dnumbuckets <=2.0 )
370+ num_buckets = 2 ;
371+ else if (dnumbuckets >= (double )0x40000000 )
372+ num_buckets = 0x40000000 ;
373+ else
374+ num_buckets = ((uint32 )1 ) <<_hash_log2 ((uint32 )dnumbuckets );
375+
376+ log2_num_buckets = _hash_log2 (num_buckets );
377+ Assert (num_buckets == (((uint32 )1 ) <<log2_num_buckets ));
378+ Assert (log2_num_buckets < HASH_MAX_SPLITPOINTS );
379+
380+ /*
381+ * We initialize the metapage, the first N bucket pages, and the first
358382 * bitmap page in sequence, using _hash_getnewbuf to cause smgrextend()
359383 * calls to occur.This ensures that the smgr level has the right idea of
360384 * the physical index length.
@@ -398,23 +422,25 @@ _hash_metapinit(Relation rel)
398422metap -> hashm_procid = index_getprocid (rel ,1 ,HASHPROC );
399423
400424/*
401- * We initialize the index with two buckets, 0 and 1, occupying physical
402- * blocks 1 and 2.The first freespace bitmap page is in block 3.
425+ * We initialize the index with N buckets, 0 .. N-1, occupying physical
426+ * blocks 1 to N. The first freespace bitmap page is in block N+1.
427+ * Since N is a power of 2, we can set the masks this way:
403428 */
404- metap -> hashm_maxbucket = metap -> hashm_lowmask = 1 ; /* nbuckets - 1 */
405- metap -> hashm_highmask = 3 ; /* (nbuckets << 1) - 1 */
429+ metap -> hashm_maxbucket = metap -> hashm_lowmask = num_buckets - 1 ;
430+ metap -> hashm_highmask = ( num_buckets <<1 )- 1 ;
406431
407432MemSet (metap -> hashm_spares ,0 ,sizeof (metap -> hashm_spares ));
408433MemSet (metap -> hashm_mapp ,0 ,sizeof (metap -> hashm_mapp ));
409434
410- metap -> hashm_spares [1 ]= 1 ;/* the first bitmap page is only spare */
411- metap -> hashm_ovflpoint = 1 ;
435+ /* Set up mapping for one spare page after the initial splitpoints */
436+ metap -> hashm_spares [log2_num_buckets ]= 1 ;
437+ metap -> hashm_ovflpoint = log2_num_buckets ;
412438metap -> hashm_firstfree = 0 ;
413439
414440/*
415- * Initialize the firsttwo buckets
441+ * Initialize the firstN buckets
416442 */
417- for (i = 0 ;i <= 1 ;i ++ )
443+ for (i = 0 ;i < num_buckets ;i ++ )
418444{
419445buf = _hash_getnewbuf (rel ,BUCKET_TO_BLKNO (metap ,i ));
420446pg = BufferGetPage (buf );
@@ -430,7 +456,7 @@ _hash_metapinit(Relation rel)
430456/*
431457 * Initialize first bitmap page
432458 */
433- _hash_initbitmap (rel ,metap ,3 );
459+ _hash_initbitmap (rel ,metap ,num_buckets + 1 );
434460
435461/* all done */
436462_hash_wrtbuf (rel ,metabuf );
@@ -511,6 +537,9 @@ _hash_expandtable(Relation rel, Buffer metabuf)
511537 * index with 2^32 buckets would certainly overflow BlockNumber and hence
512538 * _hash_alloc_buckets() would fail, but if we supported buckets smaller
513539 * than a disk block then this would be an independent constraint.
540+ *
541+ * If you change this, see also the maximum initial number of buckets
542+ * in _hash_metapinit().
514543 */
515544if (metap -> hashm_maxbucket >= (uint32 )0x7FFFFFFE )
516545gotofail ;