Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3830539

Browse files
committed
hash: Refactor hash index creation.
The primary goal here is to move all of the related page modificationsto a single section of code, in preparation for adding write-aheadlogging. In passing, rename _hash_metapinit to _hash_init, since itinitializes more than just the metapage.Amit Kapila. The larger patch series of which this is a part has beenreviewed and tested by Álvaro Herrera, Ashutosh Sharma, Mark Kirkwood,Jeff Janes, and Jesper Pedersen.
1 parent2b87dd8 commit3830539

File tree

4 files changed

+144
-135
lines changed

4 files changed

+144
-135
lines changed

‎src/backend/access/hash/hash.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
120120
estimate_rel_size(heap,NULL,&relpages,&reltuples,&allvisfrac);
121121

122122
/* Initialize the hash index metadata page and initial buckets */
123-
num_buckets=_hash_metapinit(index,reltuples,MAIN_FORKNUM);
123+
num_buckets=_hash_init(index,reltuples,MAIN_FORKNUM);
124124

125125
/*
126126
* If we just insert the tuples into the index in scan order, then
@@ -182,7 +182,7 @@ hashbuild(Relation heap, Relation index, IndexInfo *indexInfo)
182182
void
183183
hashbuildempty(Relationindex)
184184
{
185-
_hash_metapinit(index,0,INIT_FORKNUM);
185+
_hash_init(index,0,INIT_FORKNUM);
186186
}
187187

188188
/*

‎src/backend/access/hash/hashovfl.c

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -570,68 +570,6 @@ _hash_freeovflpage(Relation rel, Buffer bucketbuf, Buffer ovflbuf,
570570
}
571571

572572

573-
/*
574-
*_hash_initbitmap()
575-
*
576-
* Initialize a new bitmap page. The metapage has a write-lock upon
577-
* entering the function, and must be written by caller after return.
578-
*
579-
* 'blkno' is the block number of the new bitmap page.
580-
*
581-
* All bits in the new bitmap page are set to "1", indicating "in use".
582-
*/
583-
void
584-
_hash_initbitmap(Relationrel,HashMetaPagemetap,BlockNumberblkno,
585-
ForkNumberforkNum)
586-
{
587-
Bufferbuf;
588-
Pagepg;
589-
HashPageOpaqueop;
590-
uint32*freep;
591-
592-
/*
593-
* It is okay to write-lock the new bitmap page while holding metapage
594-
* write lock, because no one else could be contending for the new page.
595-
* Also, the metapage lock makes it safe to extend the index using
596-
* _hash_getnewbuf.
597-
*
598-
* There is some loss of concurrency in possibly doing I/O for the new
599-
* page while holding the metapage lock, but this path is taken so seldom
600-
* that it's not worth worrying about.
601-
*/
602-
buf=_hash_getnewbuf(rel,blkno,forkNum);
603-
pg=BufferGetPage(buf);
604-
605-
/* initialize the page's special space */
606-
op= (HashPageOpaque)PageGetSpecialPointer(pg);
607-
op->hasho_prevblkno=InvalidBlockNumber;
608-
op->hasho_nextblkno=InvalidBlockNumber;
609-
op->hasho_bucket=-1;
610-
op->hasho_flag=LH_BITMAP_PAGE;
611-
op->hasho_page_id=HASHO_PAGE_ID;
612-
613-
/* set all of the bits to 1 */
614-
freep=HashPageGetBitmap(pg);
615-
MemSet(freep,0xFF,BMPGSZ_BYTE(metap));
616-
617-
/* dirty the new bitmap page, and release write lock and pin */
618-
MarkBufferDirty(buf);
619-
_hash_relbuf(rel,buf);
620-
621-
/* add the new bitmap page to the metapage's list of bitmaps */
622-
/* metapage already has a write lock */
623-
if (metap->hashm_nmaps >=HASH_MAX_BITMAPS)
624-
ereport(ERROR,
625-
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
626-
errmsg("out of overflow pages in hash index \"%s\"",
627-
RelationGetRelationName(rel))));
628-
629-
metap->hashm_mapp[metap->hashm_nmaps]=blkno;
630-
631-
metap->hashm_nmaps++;
632-
}
633-
634-
635573
/*
636574
*_hash_initbitmapbuffer()
637575
*

‎src/backend/access/hash/hashpage.c

Lines changed: 136 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,36 @@ _hash_getinitbuf(Relation rel, BlockNumber blkno)
156156
returnbuf;
157157
}
158158

159+
/*
160+
*_hash_initbuf() -- Get and initialize a buffer by bucket number.
161+
*/
162+
void
163+
_hash_initbuf(Bufferbuf,uint32max_bucket,uint32num_bucket,uint32flag,
164+
boolinitpage)
165+
{
166+
HashPageOpaquepageopaque;
167+
Pagepage;
168+
169+
page=BufferGetPage(buf);
170+
171+
/* initialize the page */
172+
if (initpage)
173+
_hash_pageinit(page,BufferGetPageSize(buf));
174+
175+
pageopaque= (HashPageOpaque)PageGetSpecialPointer(page);
176+
177+
/*
178+
* Set hasho_prevblkno with current hashm_maxbucket. This value will
179+
* be used to validate cached HashMetaPageData. See
180+
* _hash_getbucketbuf_from_hashkey().
181+
*/
182+
pageopaque->hasho_prevblkno=max_bucket;
183+
pageopaque->hasho_nextblkno=InvalidBlockNumber;
184+
pageopaque->hasho_bucket=num_bucket;
185+
pageopaque->hasho_flag=flag;
186+
pageopaque->hasho_page_id=HASHO_PAGE_ID;
187+
}
188+
159189
/*
160190
*_hash_getnewbuf() -- Get a new page at the end of the index.
161191
*
@@ -288,7 +318,7 @@ _hash_dropscanbuf(Relation rel, HashScanOpaque so)
288318

289319

290320
/*
291-
*_hash_metapinit() -- Initialize the metadata page of a hash index,
321+
*_hash_init() -- Initialize the metadata page of a hash index,
292322
*the initial buckets, and the initial bitmap page.
293323
*
294324
* The initial number of buckets is dependent on num_tuples, an estimate
@@ -300,19 +330,18 @@ _hash_dropscanbuf(Relation rel, HashScanOpaque so)
300330
* multiple buffer locks is ignored.
301331
*/
302332
uint32
303-
_hash_metapinit(Relationrel,doublenum_tuples,ForkNumberforkNum)
333+
_hash_init(Relationrel,doublenum_tuples,ForkNumberforkNum)
304334
{
305-
HashMetaPagemetap;
306-
HashPageOpaquepageopaque;
307335
Buffermetabuf;
308336
Bufferbuf;
337+
Bufferbitmapbuf;
309338
Pagepg;
339+
HashMetaPagemetap;
340+
RegProcedureprocid;
310341
int32data_width;
311342
int32item_width;
312343
int32ffactor;
313-
doublednumbuckets;
314344
uint32num_buckets;
315-
uint32log2_num_buckets;
316345
uint32i;
317346

318347
/* safety check */
@@ -334,6 +363,96 @@ _hash_metapinit(Relation rel, double num_tuples, ForkNumber forkNum)
334363
if (ffactor<10)
335364
ffactor=10;
336365

366+
procid=index_getprocid(rel,1,HASHPROC);
367+
368+
/*
369+
* We initialize the metapage, the first N bucket pages, and the first
370+
* bitmap page in sequence, using _hash_getnewbuf to cause smgrextend()
371+
* calls to occur. This ensures that the smgr level has the right idea of
372+
* the physical index length.
373+
*
374+
* Critical section not required, because on error the creation of the
375+
* whole relation will be rolled back.
376+
*/
377+
metabuf=_hash_getnewbuf(rel,HASH_METAPAGE,forkNum);
378+
_hash_init_metabuffer(metabuf,num_tuples,procid,ffactor, false);
379+
MarkBufferDirty(metabuf);
380+
381+
pg=BufferGetPage(metabuf);
382+
metap=HashPageGetMeta(pg);
383+
384+
num_buckets=metap->hashm_maxbucket+1;
385+
386+
/*
387+
* Release buffer lock on the metapage while we initialize buckets.
388+
* Otherwise, we'll be in interrupt holdoff and the CHECK_FOR_INTERRUPTS
389+
* won't accomplish anything. It's a bad idea to hold buffer locks for
390+
* long intervals in any case, since that can block the bgwriter.
391+
*/
392+
LockBuffer(metabuf,BUFFER_LOCK_UNLOCK);
393+
394+
/*
395+
* Initialize and WAL Log the first N buckets
396+
*/
397+
for (i=0;i<num_buckets;i++)
398+
{
399+
BlockNumberblkno;
400+
401+
/* Allow interrupts, in case N is huge */
402+
CHECK_FOR_INTERRUPTS();
403+
404+
blkno=BUCKET_TO_BLKNO(metap,i);
405+
buf=_hash_getnewbuf(rel,blkno,forkNum);
406+
_hash_initbuf(buf,metap->hashm_maxbucket,i,LH_BUCKET_PAGE, false);
407+
MarkBufferDirty(buf);
408+
_hash_relbuf(rel,buf);
409+
}
410+
411+
/* Now reacquire buffer lock on metapage */
412+
LockBuffer(metabuf,BUFFER_LOCK_EXCLUSIVE);
413+
414+
/*
415+
* Initialize bitmap page
416+
*/
417+
bitmapbuf=_hash_getnewbuf(rel,num_buckets+1,forkNum);
418+
_hash_initbitmapbuffer(bitmapbuf,metap->hashm_bmsize, false);
419+
MarkBufferDirty(bitmapbuf);
420+
421+
/* add the new bitmap page to the metapage's list of bitmaps */
422+
/* metapage already has a write lock */
423+
if (metap->hashm_nmaps >=HASH_MAX_BITMAPS)
424+
ereport(ERROR,
425+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
426+
errmsg("out of overflow pages in hash index \"%s\"",
427+
RelationGetRelationName(rel))));
428+
429+
metap->hashm_mapp[metap->hashm_nmaps]=num_buckets+1;
430+
431+
metap->hashm_nmaps++;
432+
MarkBufferDirty(metabuf);
433+
434+
/* all done */
435+
_hash_relbuf(rel,bitmapbuf);
436+
_hash_relbuf(rel,metabuf);
437+
438+
returnnum_buckets;
439+
}
440+
441+
/*
442+
*_hash_init_metabuffer() -- Initialize the metadata page of a hash index.
443+
*/
444+
void
445+
_hash_init_metabuffer(Bufferbuf,doublenum_tuples,RegProcedureprocid,
446+
uint16ffactor,boolinitpage)
447+
{
448+
HashMetaPagemetap;
449+
HashPageOpaquepageopaque;
450+
Pagepage;
451+
doublednumbuckets;
452+
uint32num_buckets;
453+
uint32log2_num_buckets;
454+
uint32i;
455+
337456
/*
338457
* Choose the number of initial bucket pages to match the fill factor
339458
* given the estimated number of tuples. We round up the result to the
@@ -353,30 +472,25 @@ _hash_metapinit(Relation rel, double num_tuples, ForkNumber forkNum)
353472
Assert(num_buckets== (((uint32)1) <<log2_num_buckets));
354473
Assert(log2_num_buckets<HASH_MAX_SPLITPOINTS);
355474

356-
/*
357-
* We initialize the metapage, the first N bucket pages, and the first
358-
* bitmap page in sequence, using _hash_getnewbuf to cause smgrextend()
359-
* calls to occur. This ensures that the smgr level has the right idea of
360-
* the physical index length.
361-
*/
362-
metabuf=_hash_getnewbuf(rel,HASH_METAPAGE,forkNum);
363-
pg=BufferGetPage(metabuf);
475+
page=BufferGetPage(buf);
476+
if (initpage)
477+
_hash_pageinit(page,BufferGetPageSize(buf));
364478

365-
pageopaque= (HashPageOpaque)PageGetSpecialPointer(pg);
479+
pageopaque= (HashPageOpaque)PageGetSpecialPointer(page);
366480
pageopaque->hasho_prevblkno=InvalidBlockNumber;
367481
pageopaque->hasho_nextblkno=InvalidBlockNumber;
368482
pageopaque->hasho_bucket=-1;
369483
pageopaque->hasho_flag=LH_META_PAGE;
370484
pageopaque->hasho_page_id=HASHO_PAGE_ID;
371485

372-
metap=HashPageGetMeta(pg);
486+
metap=HashPageGetMeta(page);
373487

374488
metap->hashm_magic=HASH_MAGIC;
375489
metap->hashm_version=HASH_VERSION;
376490
metap->hashm_ntuples=0;
377491
metap->hashm_nmaps=0;
378492
metap->hashm_ffactor=ffactor;
379-
metap->hashm_bsize=HashGetMaxBitmapSize(pg);
493+
metap->hashm_bsize=HashGetMaxBitmapSize(page);
380494
/* find largest bitmap array size that will fit in page size */
381495
for (i=_hash_log2(metap->hashm_bsize);i>0;--i)
382496
{
@@ -393,7 +507,7 @@ _hash_metapinit(Relation rel, double num_tuples, ForkNumber forkNum)
393507
* pretty useless for normal operation (in fact, hashm_procid is not used
394508
* anywhere), but it might be handy for forensic purposes so we keep it.
395509
*/
396-
metap->hashm_procid=index_getprocid(rel,1,HASHPROC);
510+
metap->hashm_procid=procid;
397511

398512
/*
399513
* We initialize the index with N buckets, 0 .. N-1, occupying physical
@@ -411,54 +525,9 @@ _hash_metapinit(Relation rel, double num_tuples, ForkNumber forkNum)
411525
metap->hashm_ovflpoint=log2_num_buckets;
412526
metap->hashm_firstfree=0;
413527

414-
/*
415-
* Release buffer lock on the metapage while we initialize buckets.
416-
* Otherwise, we'll be in interrupt holdoff and the CHECK_FOR_INTERRUPTS
417-
* won't accomplish anything. It's a bad idea to hold buffer locks for
418-
* long intervals in any case, since that can block the bgwriter.
419-
*/
420-
MarkBufferDirty(metabuf);
421-
LockBuffer(metabuf,BUFFER_LOCK_UNLOCK);
422-
423-
/*
424-
* Initialize the first N buckets
425-
*/
426-
for (i=0;i<num_buckets;i++)
427-
{
428-
/* Allow interrupts, in case N is huge */
429-
CHECK_FOR_INTERRUPTS();
430-
431-
buf=_hash_getnewbuf(rel,BUCKET_TO_BLKNO(metap,i),forkNum);
432-
pg=BufferGetPage(buf);
433-
pageopaque= (HashPageOpaque)PageGetSpecialPointer(pg);
434-
435-
/*
436-
* Set hasho_prevblkno with current hashm_maxbucket. This value will
437-
* be used to validate cached HashMetaPageData. See
438-
* _hash_getbucketbuf_from_hashkey().
439-
*/
440-
pageopaque->hasho_prevblkno=metap->hashm_maxbucket;
441-
pageopaque->hasho_nextblkno=InvalidBlockNumber;
442-
pageopaque->hasho_bucket=i;
443-
pageopaque->hasho_flag=LH_BUCKET_PAGE;
444-
pageopaque->hasho_page_id=HASHO_PAGE_ID;
445-
MarkBufferDirty(buf);
446-
_hash_relbuf(rel,buf);
447-
}
448-
449-
/* Now reacquire buffer lock on metapage */
450-
LockBuffer(metabuf,BUFFER_LOCK_EXCLUSIVE);
451-
452-
/*
453-
* Initialize first bitmap page
454-
*/
455-
_hash_initbitmap(rel,metap,num_buckets+1,forkNum);
456-
457-
/* all done */
458-
MarkBufferDirty(metabuf);
459-
_hash_relbuf(rel,metabuf);
460-
461-
returnnum_buckets;
528+
/* Set pd_lower just past the end of the metadata. */
529+
((PageHeader)page)->pd_lower=
530+
((char*)metap+sizeof(HashMetaPageData))- (char*)page;
462531
}
463532

464533
/*
@@ -535,7 +604,7 @@ _hash_expandtable(Relation rel, Buffer metabuf)
535604
* than a disk block then this would be an independent constraint.
536605
*
537606
* If you change this, see also the maximum initial number of buckets in
538-
*_hash_metapinit().
607+
*_hash_init().
539608
*/
540609
if (metap->hashm_maxbucket >= (uint32)0x7FFFFFFE)
541610
gotofail;

‎src/include/access/hash.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,6 @@ extern Buffer _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf, bool r
311311
externBlockNumber_hash_freeovflpage(Relationrel,Bufferbucketbuf,Bufferovflbuf,
312312
Bufferwbuf,IndexTuple*itups,OffsetNumber*itup_offsets,
313313
Size*tups_size,uint16nitups,BufferAccessStrategybstrategy);
314-
externvoid_hash_initbitmap(Relationrel,HashMetaPagemetap,
315-
BlockNumberblkno,ForkNumberforkNum);
316314
externvoid_hash_initbitmapbuffer(Bufferbuf,uint16bmsize,boolinitpage);
317315
externvoid_hash_squeezebucket(Relationrel,
318316
Bucketbucket,BlockNumberbucket_blkno,
@@ -331,6 +329,8 @@ extern Buffer _hash_getbucketbuf_from_hashkey(Relation rel, uint32 hashkey,
331329
intaccess,
332330
HashMetaPage*cachedmetap);
333331
externBuffer_hash_getinitbuf(Relationrel,BlockNumberblkno);
332+
externvoid_hash_initbuf(Bufferbuf,uint32max_bucket,uint32num_bucket,
333+
uint32flag,boolinitpage);
334334
externBuffer_hash_getnewbuf(Relationrel,BlockNumberblkno,
335335
ForkNumberforkNum);
336336
externBuffer_hash_getbuf_with_strategy(Relationrel,BlockNumberblkno,
@@ -339,8 +339,10 @@ extern Buffer _hash_getbuf_with_strategy(Relation rel, BlockNumber blkno,
339339
externvoid_hash_relbuf(Relationrel,Bufferbuf);
340340
externvoid_hash_dropbuf(Relationrel,Bufferbuf);
341341
externvoid_hash_dropscanbuf(Relationrel,HashScanOpaqueso);
342-
externuint32_hash_metapinit(Relationrel,doublenum_tuples,
343-
ForkNumberforkNum);
342+
externuint32_hash_init(Relationrel,doublenum_tuples,
343+
ForkNumberforkNum);
344+
externvoid_hash_init_metabuffer(Bufferbuf,doublenum_tuples,
345+
RegProcedureprocid,uint16ffactor,boolinitpage);
344346
externvoid_hash_pageinit(Pagepage,Sizesize);
345347
externvoid_hash_expandtable(Relationrel,Buffermetabuf);
346348
externvoid_hash_finish_split(Relationrel,Buffermetabuf,Bufferobuf,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp