Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit35ea756

Browse files
committed
Refactor typcache.c's record typmod hash table.
Previously, tuple descriptors were stored in chains keyed by a fixed sizearray of OIDs. That meant there were effectively two levels of collisionchain -- one inside and one outside the hash table. Instead, let dynahash.clook after conflicts for us by supplying a proper hash and equal functionpair.This is a nice cleanup on its own, but also simplifies followupchanges allowing blessed TupleDescs to be shared between backendsparticipating in parallel query.Author: Thomas MunroReviewed-By: Andres FreundDiscussion:https://postgr.es/m/CAEepm%3D34GVhOL%2BarUx56yx7OPk7%3DqpGsv3CpO54feqjAwQKm5g%40mail.gmail.com
1 parent0052a02 commit35ea756

File tree

3 files changed

+65
-38
lines changed

3 files changed

+65
-38
lines changed

‎src/backend/access/common/tupdesc.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919

2020
#include"postgres.h"
2121

22+
#include"access/hash.h"
2223
#include"access/htup_details.h"
2324
#include"catalog/pg_collation.h"
2425
#include"catalog/pg_type.h"
2526
#include"miscadmin.h"
2627
#include"parser/parse_type.h"
2728
#include"utils/acl.h"
2829
#include"utils/builtins.h"
30+
#include"utils/hashutils.h"
2931
#include"utils/resowner_private.h"
3032
#include"utils/syscache.h"
3133

@@ -443,6 +445,31 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
443445
return true;
444446
}
445447

448+
/*
449+
* hashTupleDesc
450+
*Compute a hash value for a tuple descriptor.
451+
*
452+
* If two tuple descriptors would be considered equal by equalTupleDescs()
453+
* then their hash value will be equal according to this function.
454+
*
455+
* Note that currently contents of constraint are not hashed - it'd be a bit
456+
* painful to do so, and conflicts just due to constraints are unlikely.
457+
*/
458+
uint32
459+
hashTupleDesc(TupleDescdesc)
460+
{
461+
uint32s;
462+
inti;
463+
464+
s=hash_combine(0,hash_uint32(desc->natts));
465+
s=hash_combine(s,hash_uint32(desc->tdtypeid));
466+
s=hash_combine(s,hash_uint32(desc->tdhasoid));
467+
for (i=0;i<desc->natts;++i)
468+
s=hash_combine(s,hash_uint32(TupleDescAttr(desc,i)->atttypid));
469+
470+
returns;
471+
}
472+
446473
/*
447474
* TupleDescInitEntry
448475
*This function initializes a single attribute structure in

‎src/backend/utils/cache/typcache.c

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -133,19 +133,12 @@ typedef struct TypeCacheEnumData
133133
*
134134
* Stored record types are remembered in a linear array of TupleDescs,
135135
* which can be indexed quickly with the assigned typmod. There is also
136-
* a hash table to speed searches for matching TupleDescs. The hash key
137-
* uses just the first N columns' type OIDs, and so we may have multiple
138-
* entries with the same hash key.
136+
* a hash table to speed searches for matching TupleDescs.
139137
*/
140-
#defineREC_HASH_KEYS16/* use this many columns in hash key */
141138

142139
typedefstructRecordCacheEntry
143140
{
144-
/* the hash lookup key MUST BE FIRST */
145-
Oidhashkey[REC_HASH_KEYS];/* column type IDs, zero-filled */
146-
147-
/* list of TupleDescs for record types with this hashkey */
148-
List*tupdescs;
141+
TupleDesctupdesc;
149142
}RecordCacheEntry;
150143

151144
staticHTAB*RecordCacheHash=NULL;
@@ -1297,6 +1290,28 @@ lookup_rowtype_tupdesc_copy(Oid type_id, int32 typmod)
12971290
returnCreateTupleDescCopyConstr(tmp);
12981291
}
12991292

1293+
/*
1294+
* Hash function for the hash table of RecordCacheEntry.
1295+
*/
1296+
staticuint32
1297+
record_type_typmod_hash(constvoid*data,size_tsize)
1298+
{
1299+
RecordCacheEntry*entry= (RecordCacheEntry*)data;
1300+
1301+
returnhashTupleDesc(entry->tupdesc);
1302+
}
1303+
1304+
/*
1305+
* Match function for the hash table of RecordCacheEntry.
1306+
*/
1307+
staticint
1308+
record_type_typmod_compare(constvoid*a,constvoid*b,size_tsize)
1309+
{
1310+
RecordCacheEntry*left= (RecordCacheEntry*)a;
1311+
RecordCacheEntry*right= (RecordCacheEntry*)b;
1312+
1313+
returnequalTupleDescs(left->tupdesc,right->tupdesc) ?0 :1;
1314+
}
13001315

13011316
/*
13021317
* assign_record_type_typmod
@@ -1310,10 +1325,7 @@ assign_record_type_typmod(TupleDesc tupDesc)
13101325
{
13111326
RecordCacheEntry*recentry;
13121327
TupleDescentDesc;
1313-
Oidhashkey[REC_HASH_KEYS];
13141328
boolfound;
1315-
inti;
1316-
ListCell*l;
13171329
int32newtypmod;
13181330
MemoryContextoldcxt;
13191331

@@ -1325,45 +1337,31 @@ assign_record_type_typmod(TupleDesc tupDesc)
13251337
HASHCTLctl;
13261338

13271339
MemSet(&ctl,0,sizeof(ctl));
1328-
ctl.keysize=REC_HASH_KEYS*sizeof(Oid);
1340+
ctl.keysize=sizeof(TupleDesc);/* just the pointer */
13291341
ctl.entrysize=sizeof(RecordCacheEntry);
1342+
ctl.hash=record_type_typmod_hash;
1343+
ctl.match=record_type_typmod_compare;
13301344
RecordCacheHash=hash_create("Record information cache",64,
1331-
&ctl,HASH_ELEM |HASH_BLOBS);
1345+
&ctl,
1346+
HASH_ELEM |HASH_FUNCTION |HASH_COMPARE);
13321347

13331348
/* Also make sure CacheMemoryContext exists */
13341349
if (!CacheMemoryContext)
13351350
CreateCacheMemoryContext();
13361351
}
13371352

1338-
/* Find or create a hashtable entry for this hash class */
1339-
MemSet(hashkey,0,sizeof(hashkey));
1340-
for (i=0;i<tupDesc->natts;i++)
1341-
{
1342-
if (i >=REC_HASH_KEYS)
1343-
break;
1344-
hashkey[i]=TupleDescAttr(tupDesc,i)->atttypid;
1345-
}
1353+
/* Find or create a hashtable entry for this tuple descriptor */
13461354
recentry= (RecordCacheEntry*)hash_search(RecordCacheHash,
1347-
(void*)hashkey,
1355+
(void*)&tupDesc,
13481356
HASH_ENTER,&found);
1349-
if (!found)
1357+
if (found&&recentry->tupdesc!=NULL)
13501358
{
1351-
/* New entry ... hash_search initialized only the hash key */
1352-
recentry->tupdescs=NIL;
1353-
}
1354-
1355-
/* Look for existing record cache entry */
1356-
foreach(l,recentry->tupdescs)
1357-
{
1358-
entDesc= (TupleDesc)lfirst(l);
1359-
if (equalTupleDescs(tupDesc,entDesc))
1360-
{
1361-
tupDesc->tdtypmod=entDesc->tdtypmod;
1362-
return;
1363-
}
1359+
tupDesc->tdtypmod=recentry->tupdesc->tdtypmod;
1360+
return;
13641361
}
13651362

13661363
/* Not present, so need to manufacture an entry */
1364+
recentry->tupdesc=NULL;
13671365
oldcxt=MemoryContextSwitchTo(CacheMemoryContext);
13681366

13691367
if (RecordCacheArray==NULL)
@@ -1382,7 +1380,7 @@ assign_record_type_typmod(TupleDesc tupDesc)
13821380

13831381
/* if fail in subrs, no damage except possibly some wasted memory... */
13841382
entDesc=CreateTupleDescCopy(tupDesc);
1385-
recentry->tupdescs=lcons(entDesc,recentry->tupdescs);
1383+
recentry->tupdesc=entDesc;
13861384
/* mark it as a reference-counted tupdesc */
13871385
entDesc->tdrefcount=1;
13881386
/* now it's safe to advance NextRecordTypmod */

‎src/include/access/tupdesc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ extern void DecrTupleDescRefCount(TupleDesc tupdesc);
114114

115115
externboolequalTupleDescs(TupleDesctupdesc1,TupleDesctupdesc2);
116116

117+
externuint32hashTupleDesc(TupleDesctupdesc);
118+
117119
externvoidTupleDescInitEntry(TupleDescdesc,
118120
AttrNumberattributeNumber,
119121
constchar*attributeName,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp