diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2003-09-02 18:13:32 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2003-09-02 18:13:32 +0000 |
| commit | d70610c4eec6f6b7ca332086fdd9c91871a4718d (patch) | |
| tree | 4f61c67edf995d832789b9295149286e331acb6b /src/backend/access/hash/hashpage.c | |
| parent | 8b2450c831df5c28bb20d10d2a023ecf2349ee5b (diff) | |
| download | postgresql-d70610c4eec6f6b7ca332086fdd9c91871a4718d.tar.gz | |
Several fixes for hash indexes that involve changing the on-disk index
layout; therefore, this change forces REINDEX of hash indexes (though
not a full initdb). Widen hashm_ntuples to double so that hash space
management doesn't get confused by more than 4G entries; enlarge the
allowed number of free-space-bitmap pages; replace the useless bshift
field with a useful bmshift field; eliminate 4 bytes of wasted space
in the per-page special area.
Diffstat (limited to 'src/backend/access/hash/hashpage.c')
| -rw-r--r-- | src/backend/access/hash/hashpage.c | 90 |
1 files changed, 25 insertions, 65 deletions
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c index 23d8e0bdf6..1c16df33cd 100644 --- a/src/backend/access/hash/hashpage.c +++ b/src/backend/access/hash/hashpage.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.40 2003/09/02 02:18:38 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/hash/hashpage.c,v 1.41 2003/09/02 18:13:31 tgl Exp $ * * NOTES * Postgres hash pages look like ordinary relation pages. The opaque @@ -98,11 +98,11 @@ _hash_metapinit(Relation rel) _hash_pageinit(pg, BufferGetPageSize(metabuf)); pageopaque = (HashPageOpaque) PageGetSpecialPointer(pg); - pageopaque->hasho_oaddr = 0; pageopaque->hasho_prevblkno = InvalidBlockNumber; pageopaque->hasho_nextblkno = InvalidBlockNumber; - pageopaque->hasho_flag = LH_META_PAGE; pageopaque->hasho_bucket = -1; + pageopaque->hasho_flag = LH_META_PAGE; + pageopaque->hasho_filler = HASHO_FILL; metap = (HashMetaPage) pg; @@ -112,14 +112,17 @@ _hash_metapinit(Relation rel) metap->hashm_nmaps = 0; metap->hashm_ffactor = DEFAULT_FFACTOR; metap->hashm_bsize = BufferGetPageSize(metabuf); - metap->hashm_bshift = _hash_log2(metap->hashm_bsize); - /* page size must be power of 2 */ - Assert(metap->hashm_bsize == (1 << metap->hashm_bshift)); - /* bitmap size is half of page size, to keep it also power of 2 */ - metap->hashm_bmsize = (metap->hashm_bsize >> 1); - Assert(metap->hashm_bsize >= metap->hashm_bmsize + - MAXALIGN(sizeof(PageHeaderData)) + - MAXALIGN(sizeof(HashPageOpaqueData))); + /* find largest bitmap array size that will fit in page size */ + for (i = _hash_log2(metap->hashm_bsize); i > 0; --i) + { + if ((1 << i) <= (metap->hashm_bsize - + (MAXALIGN(sizeof(PageHeaderData)) + + MAXALIGN(sizeof(HashPageOpaqueData))))) + break; + } + Assert(i > 0); + metap->hashm_bmsize = 1 << i; + metap->hashm_bmshift = i + BYTE_TO_BIT; Assert((1 << BMPG_SHIFT(metap)) == (BMPG_MASK(metap) + 1)); metap->hashm_procid = index_getprocid(rel, 1, HASHPROC); @@ -147,11 +150,11 @@ _hash_metapinit(Relation rel) pg = BufferGetPage(buf); _hash_pageinit(pg, BufferGetPageSize(buf)); pageopaque = (HashPageOpaque) PageGetSpecialPointer(pg); - pageopaque->hasho_oaddr = 0; pageopaque->hasho_prevblkno = InvalidBlockNumber; pageopaque->hasho_nextblkno = InvalidBlockNumber; - pageopaque->hasho_flag = LH_BUCKET_PAGE; pageopaque->hasho_bucket = i; + pageopaque->hasho_flag = LH_BUCKET_PAGE; + pageopaque->hasho_filler = HASHO_FILL; _hash_wrtbuf(rel, buf); } @@ -344,49 +347,6 @@ _hash_unsetpagelock(Relation rel, } /* - * Delete a hash index item. - * - * It is safe to delete an item after acquiring a regular WRITE lock on - * the page, because no other backend can hold a READ lock on the page, - * and that means no other backend currently has an indexscan stopped on - * any item of the item being deleted. Our own backend might have such - * an indexscan (in fact *will*, since that's how VACUUM found the item - * in the first place), but _hash_adjscans will fix the scan position. - */ -void -_hash_pagedel(Relation rel, ItemPointer tid) -{ - Buffer buf; - Buffer metabuf; - Page page; - BlockNumber blkno; - OffsetNumber offno; - HashMetaPage metap; - HashPageOpaque opaque; - - blkno = ItemPointerGetBlockNumber(tid); - offno = ItemPointerGetOffsetNumber(tid); - - buf = _hash_getbuf(rel, blkno, HASH_WRITE); - page = BufferGetPage(buf); - _hash_checkpage(page, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); - opaque = (HashPageOpaque) PageGetSpecialPointer(page); - - PageIndexTupleDelete(page, offno); - - if (PageIsEmpty(page) && (opaque->hasho_flag & LH_OVERFLOW_PAGE)) - _hash_freeovflpage(rel, buf); - else - _hash_wrtbuf(rel, buf); - - metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_WRITE); - metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); - metap->hashm_ntuples--; - _hash_wrtbuf(rel, metabuf); -} - -/* * Expand the hash table by creating one new bucket. */ void @@ -398,7 +358,7 @@ _hash_expandtable(Relation rel, Buffer metabuf) uint32 spare_ndx; metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); + _hash_checkpage(rel, (Page) metap, LH_META_PAGE); _hash_chgbufaccess(rel, metabuf, HASH_READ, HASH_WRITE); @@ -474,7 +434,7 @@ _hash_splitbucket(Relation rel, TupleDesc itupdesc = RelationGetDescr(rel); metap = (HashMetaPage) BufferGetPage(metabuf); - _hash_checkpage((Page) metap, LH_META_PAGE); + _hash_checkpage(rel, (Page) metap, LH_META_PAGE); /* get the buffers & pages */ start_oblkno = BUCKET_TO_BLKNO(metap, obucket); @@ -491,9 +451,9 @@ _hash_splitbucket(Relation rel, nopaque = (HashPageOpaque) PageGetSpecialPointer(npage); nopaque->hasho_prevblkno = InvalidBlockNumber; nopaque->hasho_nextblkno = InvalidBlockNumber; - nopaque->hasho_flag = LH_BUCKET_PAGE; - nopaque->hasho_oaddr = 0; nopaque->hasho_bucket = nbucket; + nopaque->hasho_flag = LH_BUCKET_PAGE; + nopaque->hasho_filler = HASHO_FILL; _hash_wrtnorelbuf(nbuf); /* @@ -503,7 +463,7 @@ _hash_splitbucket(Relation rel, * XXX we should only need this once, if we are careful to preserve the * invariant that overflow pages are never empty. */ - _hash_checkpage(opage, LH_BUCKET_PAGE); + _hash_checkpage(rel, opage, LH_BUCKET_PAGE); oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); if (PageIsEmpty(opage)) { @@ -521,7 +481,7 @@ _hash_splitbucket(Relation rel, } obuf = _hash_getbuf(rel, oblkno, HASH_WRITE); opage = BufferGetPage(obuf); - _hash_checkpage(opage, LH_OVERFLOW_PAGE); + _hash_checkpage(rel, opage, LH_OVERFLOW_PAGE); if (PageIsEmpty(opage)) elog(ERROR, "empty hash overflow page %u", oblkno); oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); @@ -556,7 +516,7 @@ _hash_splitbucket(Relation rel, _hash_wrtbuf(rel, obuf); obuf = _hash_getbuf(rel, oblkno, HASH_WRITE); opage = BufferGetPage(obuf); - _hash_checkpage(opage, LH_OVERFLOW_PAGE); + _hash_checkpage(rel, opage, LH_OVERFLOW_PAGE); oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); /* we're guaranteed that an ovfl page has at least 1 tuple */ if (PageIsEmpty(opage)) @@ -606,7 +566,7 @@ _hash_splitbucket(Relation rel, _hash_wrtbuf(rel, nbuf); nbuf = ovflbuf; npage = BufferGetPage(nbuf); - _hash_checkpage(npage, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); + _hash_checkpage(rel, npage, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); } noffnum = OffsetNumberNext(PageGetMaxOffsetNumber(npage)); @@ -653,7 +613,7 @@ _hash_splitbucket(Relation rel, */ obuf = _hash_getbuf(rel, oblkno, HASH_WRITE); opage = BufferGetPage(obuf); - _hash_checkpage(opage, LH_OVERFLOW_PAGE); + _hash_checkpage(rel, opage, LH_OVERFLOW_PAGE); oopaque = (HashPageOpaque) PageGetSpecialPointer(opage); if (PageIsEmpty(opage)) elog(ERROR, "empty hash overflow page %u", oblkno); |
