aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2017-08-22 16:05:48 -0700
committerAndres Freund <andres@anarazel.de>2017-08-22 16:11:54 -0700
commit35ea75632a56ca8ef22aa8fed03b9dabb9c8c575 (patch)
tree630833921351b6f89f7be11372a2ac8bcba332a8 /src/backend/utils/cache
parent0052a0243d9c979a06ef273af965508103c456e0 (diff)
downloadpostgresql-35ea75632a56ca8ef22aa8fed03b9dabb9c8c575.tar.gz
postgresql-35ea75632a56ca8ef22aa8fed03b9dabb9c8c575.zip
Refactor typcache.c's record typmod hash table.
Previously, tuple descriptors were stored in chains keyed by a fixed size array of OIDs. That meant there were effectively two levels of collision chain -- one inside and one outside the hash table. Instead, let dynahash.c look after conflicts for us by supplying a proper hash and equal function pair. This is a nice cleanup on its own, but also simplifies followup changes allowing blessed TupleDescs to be shared between backends participating in parallel query. Author: Thomas Munro Reviewed-By: Andres Freund Discussion: https://postgr.es/m/CAEepm%3D34GVhOL%2BarUx56yx7OPk7%3DqpGsv3CpO54feqjAwQKm5g%40mail.gmail.com
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r--src/backend/utils/cache/typcache.c74
1 files changed, 36 insertions, 38 deletions
diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c
index 20567a394b2..691d4987b16 100644
--- a/src/backend/utils/cache/typcache.c
+++ b/src/backend/utils/cache/typcache.c
@@ -133,19 +133,12 @@ typedef struct TypeCacheEnumData
*
* Stored record types are remembered in a linear array of TupleDescs,
* which can be indexed quickly with the assigned typmod. There is also
- * a hash table to speed searches for matching TupleDescs. The hash key
- * uses just the first N columns' type OIDs, and so we may have multiple
- * entries with the same hash key.
+ * a hash table to speed searches for matching TupleDescs.
*/
-#define REC_HASH_KEYS 16 /* use this many columns in hash key */
typedef struct RecordCacheEntry
{
- /* the hash lookup key MUST BE FIRST */
- Oid hashkey[REC_HASH_KEYS]; /* column type IDs, zero-filled */
-
- /* list of TupleDescs for record types with this hashkey */
- List *tupdescs;
+ TupleDesc tupdesc;
} RecordCacheEntry;
static HTAB *RecordCacheHash = NULL;
@@ -1297,6 +1290,28 @@ lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
return CreateTupleDescCopyConstr(tmp);
}
+/*
+ * Hash function for the hash table of RecordCacheEntry.
+ */
+static uint32
+record_type_typmod_hash(const void *data, size_t size)
+{
+ RecordCacheEntry *entry = (RecordCacheEntry *) data;
+
+ return hashTupleDesc(entry->tupdesc);
+}
+
+/*
+ * Match function for the hash table of RecordCacheEntry.
+ */
+static int
+record_type_typmod_compare(const void *a, const void *b, size_t size)
+{
+ RecordCacheEntry *left = (RecordCacheEntry *) a;
+ RecordCacheEntry *right = (RecordCacheEntry *) b;
+
+ return equalTupleDescs(left->tupdesc, right->tupdesc) ? 0 : 1;
+}
/*
* assign_record_type_typmod
@@ -1310,10 +1325,7 @@ assign_record_type_typmod(TupleDesc tupDesc)
{
RecordCacheEntry *recentry;
TupleDesc entDesc;
- Oid hashkey[REC_HASH_KEYS];
bool found;
- int i;
- ListCell *l;
int32 newtypmod;
MemoryContext oldcxt;
@@ -1325,45 +1337,31 @@ assign_record_type_typmod(TupleDesc tupDesc)
HASHCTL ctl;
MemSet(&ctl, 0, sizeof(ctl));
- ctl.keysize = REC_HASH_KEYS * sizeof(Oid);
+ ctl.keysize = sizeof(TupleDesc); /* just the pointer */
ctl.entrysize = sizeof(RecordCacheEntry);
+ ctl.hash = record_type_typmod_hash;
+ ctl.match = record_type_typmod_compare;
RecordCacheHash = hash_create("Record information cache", 64,
- &ctl, HASH_ELEM | HASH_BLOBS);
+ &ctl,
+ HASH_ELEM | HASH_FUNCTION | HASH_COMPARE);
/* Also make sure CacheMemoryContext exists */
if (!CacheMemoryContext)
CreateCacheMemoryContext();
}
- /* Find or create a hashtable entry for this hash class */
- MemSet(hashkey, 0, sizeof(hashkey));
- for (i = 0; i < tupDesc->natts; i++)
- {
- if (i >= REC_HASH_KEYS)
- break;
- hashkey[i] = TupleDescAttr(tupDesc, i)->atttypid;
- }
+ /* Find or create a hashtable entry for this tuple descriptor */
recentry = (RecordCacheEntry *) hash_search(RecordCacheHash,
- (void *) hashkey,
+ (void *) &tupDesc,
HASH_ENTER, &found);
- if (!found)
+ if (found && recentry->tupdesc != NULL)
{
- /* New entry ... hash_search initialized only the hash key */
- recentry->tupdescs = NIL;
- }
-
- /* Look for existing record cache entry */
- foreach(l, recentry->tupdescs)
- {
- entDesc = (TupleDesc) lfirst(l);
- if (equalTupleDescs(tupDesc, entDesc))
- {
- tupDesc->tdtypmod = entDesc->tdtypmod;
- return;
- }
+ tupDesc->tdtypmod = recentry->tupdesc->tdtypmod;
+ return;
}
/* Not present, so need to manufacture an entry */
+ recentry->tupdesc = NULL;
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
if (RecordCacheArray == NULL)
@@ -1382,7 +1380,7 @@ assign_record_type_typmod(TupleDesc tupDesc)
/* if fail in subrs, no damage except possibly some wasted memory... */
entDesc = CreateTupleDescCopy(tupDesc);
- recentry->tupdescs = lcons(entDesc, recentry->tupdescs);
+ recentry->tupdesc = entDesc;
/* mark it as a reference-counted tupdesc */
entDesc->tdrefcount = 1;
/* now it's safe to advance NextRecordTypmod */