mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Introduce TupleHashTableHash() and LookupTupleHashEntryHash().
Expose two new entry points: one for only calculating the hash value of a tuple, and another for looking up a hash entry when the hash value is already known. This will be useful for disk-based Hash Aggregation to avoid recomputing the hash value for the same tuple after saving and restoring it from disk. Discussion: https://postgr.es/m/37091115219dd522fd9ed67333ee8ed1b7e09443.camel%40j-davis.com
This commit is contained in:
parent
e6f86f8dd9
commit
4eaea3db15
@ -25,8 +25,9 @@
|
|||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
|
|
||||||
static uint32 TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple);
|
|
||||||
static int TupleHashTableMatch(struct tuplehash_hash *tb, const MinimalTuple tuple1, const MinimalTuple tuple2);
|
static int TupleHashTableMatch(struct tuplehash_hash *tb, const MinimalTuple tuple1, const MinimalTuple tuple2);
|
||||||
|
static TupleHashEntry LookupTupleHashEntry_internal(
|
||||||
|
TupleHashTable hashtable, TupleTableSlot *slot, bool *isnew, uint32 hash);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define parameters for tuple hash table code generation. The interface is
|
* Define parameters for tuple hash table code generation. The interface is
|
||||||
@ -300,10 +301,9 @@ TupleHashEntry
|
|||||||
LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
|
LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
|
||||||
bool *isnew)
|
bool *isnew)
|
||||||
{
|
{
|
||||||
TupleHashEntryData *entry;
|
TupleHashEntry entry;
|
||||||
MemoryContext oldContext;
|
MemoryContext oldContext;
|
||||||
bool found;
|
uint32 hash;
|
||||||
MinimalTuple key;
|
|
||||||
|
|
||||||
/* Need to run the hash functions in short-lived context */
|
/* Need to run the hash functions in short-lived context */
|
||||||
oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
|
oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
|
||||||
@ -313,32 +313,34 @@ LookupTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
|
|||||||
hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
|
hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
|
||||||
hashtable->cur_eq_func = hashtable->tab_eq_func;
|
hashtable->cur_eq_func = hashtable->tab_eq_func;
|
||||||
|
|
||||||
key = NULL; /* flag to reference inputslot */
|
hash = TupleHashTableHash(hashtable->hashtab, NULL);
|
||||||
|
entry = LookupTupleHashEntry_internal(hashtable, slot, isnew, hash);
|
||||||
|
|
||||||
if (isnew)
|
MemoryContextSwitchTo(oldContext);
|
||||||
{
|
|
||||||
entry = tuplehash_insert(hashtable->hashtab, key, &found);
|
|
||||||
|
|
||||||
if (found)
|
return entry;
|
||||||
{
|
}
|
||||||
/* found pre-existing entry */
|
|
||||||
*isnew = false;
|
/*
|
||||||
}
|
* A variant of LookupTupleHashEntry for callers that have already computed
|
||||||
else
|
* the hash value.
|
||||||
{
|
*/
|
||||||
/* created new entry */
|
TupleHashEntry
|
||||||
*isnew = true;
|
LookupTupleHashEntryHash(TupleHashTable hashtable, TupleTableSlot *slot,
|
||||||
/* zero caller data */
|
bool *isnew, uint32 hash)
|
||||||
entry->additional = NULL;
|
{
|
||||||
MemoryContextSwitchTo(hashtable->tablecxt);
|
TupleHashEntry entry;
|
||||||
/* Copy the first tuple into the table context */
|
MemoryContext oldContext;
|
||||||
entry->firstTuple = ExecCopySlotMinimalTuple(slot);
|
|
||||||
}
|
/* Need to run the hash functions in short-lived context */
|
||||||
}
|
oldContext = MemoryContextSwitchTo(hashtable->tempcxt);
|
||||||
else
|
|
||||||
{
|
/* set up data needed by hash and match functions */
|
||||||
entry = tuplehash_lookup(hashtable->hashtab, key);
|
hashtable->inputslot = slot;
|
||||||
}
|
hashtable->in_hash_funcs = hashtable->tab_hash_funcs;
|
||||||
|
hashtable->cur_eq_func = hashtable->tab_eq_func;
|
||||||
|
|
||||||
|
entry = LookupTupleHashEntry_internal(hashtable, slot, isnew, hash);
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldContext);
|
MemoryContextSwitchTo(oldContext);
|
||||||
|
|
||||||
@ -389,7 +391,7 @@ FindTupleHashEntry(TupleHashTable hashtable, TupleTableSlot *slot,
|
|||||||
* Also, the caller must select an appropriate memory context for running
|
* Also, the caller must select an appropriate memory context for running
|
||||||
* the hash functions. (dynahash.c doesn't change CurrentMemoryContext.)
|
* the hash functions. (dynahash.c doesn't change CurrentMemoryContext.)
|
||||||
*/
|
*/
|
||||||
static uint32
|
uint32
|
||||||
TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple)
|
TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple)
|
||||||
{
|
{
|
||||||
TupleHashTable hashtable = (TupleHashTable) tb->private_data;
|
TupleHashTable hashtable = (TupleHashTable) tb->private_data;
|
||||||
@ -450,6 +452,52 @@ TupleHashTableHash(struct tuplehash_hash *tb, const MinimalTuple tuple)
|
|||||||
return murmurhash32(hashkey);
|
return murmurhash32(hashkey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does the work of LookupTupleHashEntry and LookupTupleHashEntryHash. Useful
|
||||||
|
* so that we can avoid switching the memory context multiple times for
|
||||||
|
* LookupTupleHashEntry.
|
||||||
|
*
|
||||||
|
* NB: This function may or may not change the memory context. Caller is
|
||||||
|
* expected to change it back.
|
||||||
|
*/
|
||||||
|
static TupleHashEntry
|
||||||
|
LookupTupleHashEntry_internal(TupleHashTable hashtable, TupleTableSlot *slot,
|
||||||
|
bool *isnew, uint32 hash)
|
||||||
|
{
|
||||||
|
TupleHashEntryData *entry;
|
||||||
|
bool found;
|
||||||
|
MinimalTuple key;
|
||||||
|
|
||||||
|
key = NULL; /* flag to reference inputslot */
|
||||||
|
|
||||||
|
if (isnew)
|
||||||
|
{
|
||||||
|
entry = tuplehash_insert_hash(hashtable->hashtab, key, hash, &found);
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
/* found pre-existing entry */
|
||||||
|
*isnew = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* created new entry */
|
||||||
|
*isnew = true;
|
||||||
|
/* zero caller data */
|
||||||
|
entry->additional = NULL;
|
||||||
|
MemoryContextSwitchTo(hashtable->tablecxt);
|
||||||
|
/* Copy the first tuple into the table context */
|
||||||
|
entry->firstTuple = ExecCopySlotMinimalTuple(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry = tuplehash_lookup_hash(hashtable->hashtab, key, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See whether two tuples (presumably of the same hash value) match
|
* See whether two tuples (presumably of the same hash value) match
|
||||||
*/
|
*/
|
||||||
|
@ -140,6 +140,11 @@ extern TupleHashTable BuildTupleHashTableExt(PlanState *parent,
|
|||||||
extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable,
|
extern TupleHashEntry LookupTupleHashEntry(TupleHashTable hashtable,
|
||||||
TupleTableSlot *slot,
|
TupleTableSlot *slot,
|
||||||
bool *isnew);
|
bool *isnew);
|
||||||
|
extern uint32 TupleHashTableHash(struct tuplehash_hash *tb,
|
||||||
|
const MinimalTuple tuple);
|
||||||
|
extern TupleHashEntry LookupTupleHashEntryHash(TupleHashTable hashtable,
|
||||||
|
TupleTableSlot *slot,
|
||||||
|
bool *isnew, uint32 hash);
|
||||||
extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable,
|
extern TupleHashEntry FindTupleHashEntry(TupleHashTable hashtable,
|
||||||
TupleTableSlot *slot,
|
TupleTableSlot *slot,
|
||||||
ExprState *eqcomp,
|
ExprState *eqcomp,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user