mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +03:00
Change hash indexes to store only the hash code rather than the whole indexed
value. This means that hash index lookups are always lossy and have to be rechecked when the heap is visited; however, the gain in index compactness outweighs this when the indexed values are wide. Also, we only need to perform datatype comparisons when the hash codes match exactly, rather than for every entry in the hash bucket; so it could also win for datatypes that have expensive comparison functions. A small additional win is gained by keeping hash index pages sorted by hash code and using binary search to reduce the number of index tuples we have to look at. Xiao Meng This commit also incorporates Zdenek Kotala's patch to isolate hash metapages and hash bitmaps a bit better from the page header datastructures.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.50 2008/06/19 00:46:03 alvherre Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.51 2008/09/15 18:43:41 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -43,18 +43,11 @@ _hash_doinsert(Relation rel, IndexTuple itup)
|
||||
bool do_expand;
|
||||
uint32 hashkey;
|
||||
Bucket bucket;
|
||||
Datum datum;
|
||||
bool isnull;
|
||||
|
||||
/*
|
||||
* Compute the hash key for the item. We do this first so as not to need
|
||||
* to hold any locks while running the hash function.
|
||||
* Get the hash key for the item (it's stored in the index tuple itself).
|
||||
*/
|
||||
if (rel->rd_rel->relnatts != 1)
|
||||
elog(ERROR, "hash indexes support only one index key");
|
||||
datum = index_getattr(itup, 1, RelationGetDescr(rel), &isnull);
|
||||
Assert(!isnull);
|
||||
hashkey = _hash_datum2hashkey(rel, datum);
|
||||
hashkey = _hash_get_indextuple_hashkey(itup);
|
||||
|
||||
/* compute item size too */
|
||||
itemsz = IndexTupleDSize(*itup);
|
||||
@@ -69,12 +62,14 @@ _hash_doinsert(Relation rel, IndexTuple itup)
|
||||
|
||||
/* Read the metapage */
|
||||
metabuf = _hash_getbuf(rel, HASH_METAPAGE, HASH_READ, LH_META_PAGE);
|
||||
metap = (HashMetaPage) BufferGetPage(metabuf);
|
||||
metap = HashPageGetMeta(BufferGetPage(metabuf));
|
||||
|
||||
/*
|
||||
* Check whether the item can fit on a hash page at all. (Eventually, we
|
||||
* ought to try to apply TOAST methods if not.) Note that at this point,
|
||||
* itemsz doesn't include the ItemId.
|
||||
*
|
||||
* XXX this is useless code if we are only storing hash keys.
|
||||
*/
|
||||
if (itemsz > HashMaxItemSize((Page) metap))
|
||||
ereport(ERROR,
|
||||
@@ -197,11 +192,15 @@ _hash_pgaddtup(Relation rel,
|
||||
{
|
||||
OffsetNumber itup_off;
|
||||
Page page;
|
||||
uint32 hashkey;
|
||||
|
||||
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
|
||||
page = BufferGetPage(buf);
|
||||
|
||||
itup_off = OffsetNumberNext(PageGetMaxOffsetNumber(page));
|
||||
/* Find where to insert the tuple (preserving page's hashkey ordering) */
|
||||
hashkey = _hash_get_indextuple_hashkey(itup);
|
||||
itup_off = _hash_binsearch(page, hashkey);
|
||||
|
||||
if (PageAddItem(page, (Item) itup, itemsize, itup_off, false, false)
|
||||
== InvalidOffsetNumber)
|
||||
elog(ERROR, "failed to add index item to \"%s\"",
|
||||
|
||||
Reference in New Issue
Block a user