Introduce hash_search_with_hash_value() function

This new function iterates hash entries with given hash values.  This function
is designed to avoid full sequential hash search in the syscache invalidation
callbacks.

Discussion: https://postgr.es/m/5812a6e5-68ae-4d84-9d85-b443176966a1%40sigaev.ru
Author: Teodor Sigaev
Reviewed-by: Aleksander Alekseev, Tom Lane, Michael Paquier, Roman Zharkov
Reviewed-by: Andrei Lepikhov
This commit is contained in:
Alexander Korotkov 2024-08-07 06:51:16 +03:00
parent 3ab2668d48
commit d0f020037e
2 changed files with 43 additions and 0 deletions

View File

@ -1387,10 +1387,30 @@ hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
status->hashp = hashp;
status->curBucket = 0;
status->curEntry = NULL;
status->hasHashvalue = false;
if (!hashp->frozen)
register_seq_scan(hashp);
}
/*
* Same as above but scan by the given hash value.
* See also hash_seq_search().
*/
void
hash_seq_init_with_hash_value(HASH_SEQ_STATUS *status, HTAB *hashp,
uint32 hashvalue)
{
HASHBUCKET *bucketPtr;
hash_seq_init(status, hashp);
status->hasHashvalue = true;
status->hashvalue = hashvalue;
status->curBucket = hash_initial_lookup(hashp, hashvalue, &bucketPtr);
status->curEntry = *bucketPtr;
}
void *
hash_seq_search(HASH_SEQ_STATUS *status)
{
@ -1404,6 +1424,24 @@ hash_seq_search(HASH_SEQ_STATUS *status)
uint32 curBucket;
HASHELEMENT *curElem;
if (status->hasHashvalue)
{
/*
* Scan entries only in the current bucket because only this bucket
* can contain entries with the given hash value.
*/
while ((curElem = status->curEntry) != NULL)
{
status->curEntry = curElem->link;
if (status->hashvalue != curElem->hashvalue)
continue;
return (void *) ELEMENTKEY(curElem);
}
hash_seq_term(status);
return NULL;
}
if ((curElem = status->curEntry) != NULL)
{
/* Continuing scan of curBucket... */

View File

@ -122,6 +122,8 @@ typedef struct
HTAB *hashp;
uint32 curBucket; /* index of current bucket */
HASHELEMENT *curEntry; /* current entry in bucket */
bool hasHashvalue; /* true if hashvalue was provided */
uint32 hashvalue; /* hashvalue to start seqscan over hash */
} HASH_SEQ_STATUS;
/*
@ -141,6 +143,9 @@ extern bool hash_update_hash_key(HTAB *hashp, void *existingEntry,
const void *newKeyPtr);
extern long hash_get_num_entries(HTAB *hashp);
extern void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp);
extern void hash_seq_init_with_hash_value(HASH_SEQ_STATUS *status,
HTAB *hashp,
uint32 hashvalue);
extern void *hash_seq_search(HASH_SEQ_STATUS *status);
extern void hash_seq_term(HASH_SEQ_STATUS *status);
extern void hash_freeze(HTAB *hashp);