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:
parent
3ab2668d48
commit
d0f020037e
@ -1387,10 +1387,30 @@ hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
|
|||||||
status->hashp = hashp;
|
status->hashp = hashp;
|
||||||
status->curBucket = 0;
|
status->curBucket = 0;
|
||||||
status->curEntry = NULL;
|
status->curEntry = NULL;
|
||||||
|
status->hasHashvalue = false;
|
||||||
if (!hashp->frozen)
|
if (!hashp->frozen)
|
||||||
register_seq_scan(hashp);
|
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 *
|
void *
|
||||||
hash_seq_search(HASH_SEQ_STATUS *status)
|
hash_seq_search(HASH_SEQ_STATUS *status)
|
||||||
{
|
{
|
||||||
@ -1404,6 +1424,24 @@ hash_seq_search(HASH_SEQ_STATUS *status)
|
|||||||
uint32 curBucket;
|
uint32 curBucket;
|
||||||
HASHELEMENT *curElem;
|
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)
|
if ((curElem = status->curEntry) != NULL)
|
||||||
{
|
{
|
||||||
/* Continuing scan of curBucket... */
|
/* Continuing scan of curBucket... */
|
||||||
|
@ -122,6 +122,8 @@ typedef struct
|
|||||||
HTAB *hashp;
|
HTAB *hashp;
|
||||||
uint32 curBucket; /* index of current bucket */
|
uint32 curBucket; /* index of current bucket */
|
||||||
HASHELEMENT *curEntry; /* current entry in 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;
|
} HASH_SEQ_STATUS;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -141,6 +143,9 @@ extern bool hash_update_hash_key(HTAB *hashp, void *existingEntry,
|
|||||||
const void *newKeyPtr);
|
const void *newKeyPtr);
|
||||||
extern long hash_get_num_entries(HTAB *hashp);
|
extern long hash_get_num_entries(HTAB *hashp);
|
||||||
extern void hash_seq_init(HASH_SEQ_STATUS *status, 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_search(HASH_SEQ_STATUS *status);
|
||||||
extern void hash_seq_term(HASH_SEQ_STATUS *status);
|
extern void hash_seq_term(HASH_SEQ_STATUS *status);
|
||||||
extern void hash_freeze(HTAB *hashp);
|
extern void hash_freeze(HTAB *hashp);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user