Remove the limit on the number of entries allowed in catcaches, and

remove the infrastructure needed to enforce the limit, ie, the global
LRU list of cache entries.  On small-to-middling databases this wins
because maintaining the LRU list is a waste of time.  On large databases
this wins because it's better to keep more cache entries (we assume
such users can afford to use some more per-backend memory than was
contemplated in the Berkeley-era catcache design).  This provides a
noticeable improvement in the speed of psql \d on a 10000-table
database, though it doesn't make it instantaneous.

While at it, use per-catcache settings for the number of hash buckets
per catcache, rather than the former one-size-fits-all value.  It's a
bit silly to be using the same number of hash buckets for, eg, pg_am
and pg_attribute.  The specific values I used might need some tuning,
but they seem to be in the right ballpark based on CATCACHE_STATS
results from the standard regression tests.
This commit is contained in:
Tom Lane 2006-06-15 02:08:09 +00:00
parent e1e133f264
commit 8b9bc234ad
3 changed files with 181 additions and 206 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.128 2006/03/05 15:58:45 momjian Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.129 2006/06/15 02:08:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -37,20 +37,6 @@
/* #define CACHEDEBUG */ /* turns DEBUG elogs on */
/*
* Constants related to size of the catcache.
*
* NCCBUCKETS must be a power of two and must be less than 64K (because
* SharedInvalCatcacheMsg crams hash indexes into a uint16 field). In
* practice it should be a lot less, anyway, to avoid chewing up too much
* space on hash bucket headers.
*
* MAXCCTUPLES could be as small as a few hundred, if per-backend memory
* consumption is at a premium.
*/
#define NCCBUCKETS 256 /* Hash buckets per CatCache */
#define MAXCCTUPLES 5000 /* Maximum # of tuples in all caches */
/*
* Given a hash value and the size of the hash table, find the bucket
* in which the hash value belongs. Since the hash table must contain
@ -89,7 +75,7 @@ static uint32 CatalogCacheComputeTupleHashValue(CatCache *cache,
HeapTuple tuple);
#ifdef CATCACHE_STATS
static void CatCachePrintStats(void);
static void CatCachePrintStats(int code, Datum arg);
#endif
static void CatCacheRemoveCTup(CatCache *cache, CatCTup *ct);
static void CatCacheRemoveCList(CatCache *cache, CatCList *cl);
@ -97,7 +83,6 @@ static void CatalogCacheInitializeCache(CatCache *cache);
static CatCTup *CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp,
uint32 hashValue, Index hashIndex,
bool negative);
static void CatalogCacheCleanup(CatCTup *savect);
static HeapTuple build_dummy_tuple(CatCache *cache, int nkeys, ScanKey skeys);
@ -281,7 +266,7 @@ CatalogCacheComputeTupleHashValue(CatCache *cache, HeapTuple tuple)
#ifdef CATCACHE_STATS
static void
CatCachePrintStats(void)
CatCachePrintStats(int code, Datum arg)
{
CatCache *cache;
long cc_searches = 0;
@ -289,18 +274,14 @@ CatCachePrintStats(void)
long cc_neg_hits = 0;
long cc_newloads = 0;
long cc_invals = 0;
long cc_discards = 0;
long cc_lsearches = 0;
long cc_lhits = 0;
elog(DEBUG2, "catcache stats dump: %d/%d tuples in catcaches",
CacheHdr->ch_ntup, CacheHdr->ch_maxtup);
for (cache = CacheHdr->ch_caches; cache; cache = cache->cc_next)
{
if (cache->cc_ntup == 0 && cache->cc_searches == 0)
continue; /* don't print unused caches */
elog(DEBUG2, "catcache %s/%u: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld discards, %ld lsrch, %ld lhits",
elog(DEBUG2, "catcache %s/%u: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld lsrch, %ld lhits",
cache->cc_relname,
cache->cc_indexoid,
cache->cc_ntup,
@ -312,7 +293,6 @@ CatCachePrintStats(void)
cache->cc_searches - cache->cc_hits - cache->cc_neg_hits - cache->cc_newloads,
cache->cc_searches - cache->cc_hits - cache->cc_neg_hits,
cache->cc_invals,
cache->cc_discards,
cache->cc_lsearches,
cache->cc_lhits);
cc_searches += cache->cc_searches;
@ -320,11 +300,10 @@ CatCachePrintStats(void)
cc_neg_hits += cache->cc_neg_hits;
cc_newloads += cache->cc_newloads;
cc_invals += cache->cc_invals;
cc_discards += cache->cc_discards;
cc_lsearches += cache->cc_lsearches;
cc_lhits += cache->cc_lhits;
}
elog(DEBUG2, "catcache totals: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld discards, %ld lsrch, %ld lhits",
elog(DEBUG2, "catcache totals: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld lsrch, %ld lhits",
CacheHdr->ch_ntup,
cc_searches,
cc_hits,
@ -334,7 +313,6 @@ CatCachePrintStats(void)
cc_searches - cc_hits - cc_neg_hits - cc_newloads,
cc_searches - cc_hits - cc_neg_hits,
cc_invals,
cc_discards,
cc_lsearches,
cc_lhits);
}
@ -367,8 +345,7 @@ CatCacheRemoveCTup(CatCache *cache, CatCTup *ct)
return; /* nothing left to do */
}
/* delink from linked lists */
DLRemove(&ct->lrulist_elem);
/* delink from linked list */
DLRemove(&ct->cache_elem);
/* free associated tuple data */
@ -568,11 +545,13 @@ AtEOXact_CatCache(bool isCommit)
if (assert_enabled)
{
CatCache *ccp;
Dlelem *elt;
/* Check CatCLists */
for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
{
Dlelem *elt;
int i;
/* Check CatCLists */
for (elt = DLGetHead(&ccp->cc_lists); elt; elt = DLGetSucc(elt))
{
CatCList *cl = (CatCList *) DLE_VAL(elt);
@ -581,16 +560,21 @@ AtEOXact_CatCache(bool isCommit)
Assert(cl->refcount == 0);
Assert(!cl->dead);
}
}
/* Check individual tuples */
for (elt = DLGetHead(&CacheHdr->ch_lrulist); elt; elt = DLGetSucc(elt))
{
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
/* Check individual tuples */
for (i = 0; i < ccp->cc_nbuckets; i++)
{
for (elt = DLGetHead(&ccp->cc_bucket[i]);
elt;
elt = DLGetSucc(elt))
{
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
Assert(ct->ct_magic == CT_MAGIC);
Assert(ct->refcount == 0);
Assert(!ct->dead);
Assert(ct->ct_magic == CT_MAGIC);
Assert(ct->refcount == 0);
Assert(!ct->dead);
}
}
}
}
#endif
@ -796,12 +780,27 @@ InitCatCache(int id,
Oid indexoid,
int reloidattr,
int nkeys,
const int *key)
const int *key,
int nbuckets)
{
CatCache *cp;
MemoryContext oldcxt;
int i;
/*
* nbuckets is the number of hash buckets to use in this catcache.
* Currently we just use a hard-wired estimate of an appropriate size
* for each cache; maybe later make them dynamically resizable?
*
* nbuckets must be a power of two. We check this via Assert rather than
* a full runtime check because the values will be coming from constant
* tables.
*
* If you're confused by the power-of-two check, see comments in
* bitmapset.c for an explanation.
*/
Assert(nbuckets > 0 && (nbuckets & -nbuckets) == nbuckets);
/*
* first switch to the cache context so our allocations do not vanish at
* the end of a transaction
@ -812,17 +811,15 @@ InitCatCache(int id,
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
/*
* if first time through, initialize the cache group header, including
* global LRU list header
* if first time through, initialize the cache group header
*/
if (CacheHdr == NULL)
{
CacheHdr = (CatCacheHeader *) palloc(sizeof(CatCacheHeader));
CacheHdr->ch_caches = NULL;
CacheHdr->ch_ntup = 0;
CacheHdr->ch_maxtup = MAXCCTUPLES;
DLInitList(&CacheHdr->ch_lrulist);
#ifdef CATCACHE_STATS
/* set up to dump stats at backend exit */
on_proc_exit(CatCachePrintStats, 0);
#endif
}
@ -832,7 +829,7 @@ InitCatCache(int id,
*
* Note: we assume zeroing initializes the Dllist headers correctly
*/
cp = (CatCache *) palloc0(sizeof(CatCache) + NCCBUCKETS * sizeof(Dllist));
cp = (CatCache *) palloc0(sizeof(CatCache) + nbuckets * sizeof(Dllist));
/*
* initialize the cache's relation information for the relation
@ -847,7 +844,7 @@ InitCatCache(int id,
cp->cc_tupdesc = (TupleDesc) NULL;
cp->cc_reloidattr = reloidattr;
cp->cc_ntup = 0;
cp->cc_nbuckets = NCCBUCKETS;
cp->cc_nbuckets = nbuckets;
cp->cc_nkeys = nkeys;
for (i = 0; i < nkeys; ++i)
cp->cc_key[i] = key[i];
@ -1162,13 +1159,11 @@ SearchCatCache(CatCache *cache,
continue;
/*
* we found a match in the cache: move it to the front of the global
* LRU list. We also move it to the front of the list for its
* hashbucket, in order to speed subsequent searches. (The most
* frequently accessed elements in any hashbucket will tend to be near
* the front of the hashbucket's list.)
* We found a match in the cache. Move it to the front of the list
* for its hashbucket, in order to speed subsequent searches. (The
* most frequently accessed elements in any hashbucket will tend to be
* near the front of the hashbucket's list.)
*/
DLMoveToFront(&ct->lrulist_elem);
DLMoveToFront(&ct->cache_elem);
/*
@ -1414,14 +1409,12 @@ SearchCatCacheList(CatCache *cache,
continue;
/*
* We found a matching list: mark it as touched since the last
* CatalogCacheCleanup() sweep. Also move the list to the front of
* the cache's list-of-lists, to speed subsequent searches. (We do not
* We found a matching list. Move the list to the front of the
* cache's list-of-lists, to speed subsequent searches. (We do not
* move the members to the fronts of their hashbucket lists, however,
* since there's no point in that unless they are searched for
* individually.)
*/
cl->touched = true;
DLMoveToFront(&cl->cache_elem);
/* Bump the list's refcount and return it */
@ -1504,10 +1497,7 @@ SearchCatCacheList(CatCache *cache,
if (ct->c_list)
continue;
/* Found a match, so move it to front */
DLMoveToFront(&ct->lrulist_elem);
break;
break; /* A-OK */
}
if (elt == NULL)
@ -1577,7 +1567,6 @@ SearchCatCacheList(CatCache *cache,
cl->refcount = 0; /* for the moment */
cl->dead = false;
cl->ordered = ordered;
cl->touched = false; /* we already moved members to front */
cl->nkeys = nkeys;
cl->hash_value = lHashValue;
cl->n_members = nmembers;
@ -1654,11 +1643,10 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp,
/*
* Finish initializing the CatCTup header, and add it to the cache's
* linked lists and counts.
* linked list and counts.
*/
ct->ct_magic = CT_MAGIC;
ct->my_cache = cache;
DLInitElem(&ct->lrulist_elem, (void *) ct);
DLInitElem(&ct->cache_elem, (void *) ct);
ct->c_list = NULL;
ct->refcount = 0; /* for the moment */
@ -1666,97 +1654,14 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp,
ct->negative = negative;
ct->hash_value = hashValue;
DLAddHead(&CacheHdr->ch_lrulist, &ct->lrulist_elem);
DLAddHead(&cache->cc_bucket[hashIndex], &ct->cache_elem);
cache->cc_ntup++;
CacheHdr->ch_ntup++;
/*
* If we've exceeded the desired size of the caches, try to throw away the
* least recently used entry(s). NB: be careful not to throw away the
* newly-built entry...
*/
if (CacheHdr->ch_ntup > CacheHdr->ch_maxtup)
CatalogCacheCleanup(ct);
return ct;
}
/*
* CatalogCacheCleanup
* Try to reduce the size of the catcaches when they get too big
*
* savect can be NULL, or a specific CatCTup not to remove even if it
* has zero refcount.
*/
static void
CatalogCacheCleanup(CatCTup *savect)
{
int tup_target;
CatCache *ccp;
Dlelem *elt,
*prevelt;
/*
* Each time we have to do this, try to cut the cache size down to about
* 90% of the maximum.
*/
tup_target = (CacheHdr->ch_maxtup * 9) / 10;
/*
* Our strategy for managing CatCLists is that, each time we have to throw
* away some cache entries, we first move-to-front all the members of
* CatCLists that have been touched since the last cleanup sweep. Then we
* do strict LRU elimination by individual tuples, zapping a list if any
* of its members gets zapped. Before PostgreSQL 8.1, we moved members to
* front each time their owning list was touched, which was arguably more
* fair in balancing list members against standalone tuples --- but the
* overhead for large lists was horrendous. This scheme is more heavily
* biased towards preserving lists, but that is not necessarily bad
* either.
*/
for (ccp = CacheHdr->ch_caches; ccp; ccp = ccp->cc_next)
{
for (elt = DLGetHead(&ccp->cc_lists); elt; elt = DLGetSucc(elt))
{
CatCList *cl = (CatCList *) DLE_VAL(elt);
Assert(cl->cl_magic == CL_MAGIC);
if (cl->touched && !cl->dead)
{
int i;
for (i = 0; i < cl->n_members; i++)
DLMoveToFront(&cl->members[i]->lrulist_elem);
}
cl->touched = false;
}
}
/* Now get rid of unreferenced tuples in reverse global LRU order */
for (elt = DLGetTail(&CacheHdr->ch_lrulist); elt; elt = prevelt)
{
CatCTup *ct = (CatCTup *) DLE_VAL(elt);
prevelt = DLGetPred(elt);
if (ct->refcount == 0 &&
(ct->c_list == NULL || ct->c_list->refcount == 0) &&
ct != savect)
{
#ifdef CATCACHE_STATS
ct->my_cache->cc_discards++;
#endif
CatCacheRemoveCTup(ct->my_cache, ct);
/* Quit when we've removed enough tuples */
if (CacheHdr->ch_ntup <= tup_target)
break;
}
}
}
/*
* build_dummy_tuple
* Generate a palloc'd HeapTuple that contains the specified key

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.103 2006/05/03 22:45:26 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.104 2006/06/15 02:08:09 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@ -55,14 +55,18 @@
the list sorted alphabetically and adjust the cache numbers
accordingly.
Add your entry to the cacheinfo[] array below. All cache lists are
alphabetical, so add it in the proper place. Specify the relation
OID, index OID, number of keys, and key attribute numbers. If the
relation contains tuples that are associated with a particular relation
(for example, its attributes, rules, triggers, etc) then specify the
attribute number that contains the OID of the associated relation.
This is used by CatalogCacheFlushRelation() to remove the correct
tuples during a table drop or relcache invalidation event.
Add your entry to the cacheinfo[] array below. All cache lists are
alphabetical, so add it in the proper place. Specify the relation OID,
index OID, number of keys, key attribute numbers, and number of hash
buckets. If the relation contains tuples that are associated with a
particular relation (for example, its attributes, rules, triggers, etc)
then specify the attribute number that contains the OID of the associated
relation. This is used by CatalogCacheFlushRelation() to remove the
correct tuples during a table drop or relcache invalidation event.
The number of hash buckets must be a power of 2. It's reasonable to
set this to the number of entries that might be in the particular cache
in a medium-size database.
There must be a unique index underlying each syscache (ie, an index
whose key is the same as that of the cache). If there is not one
@ -90,6 +94,7 @@ struct cachedesc
int reloidattr; /* attr number of rel OID reference, or 0 */
int nkeys; /* # of keys needed for cache lookup */
int key[4]; /* attribute numbers of key attrs */
int nbuckets; /* number of hash buckets for this cache */
};
static const struct cachedesc cacheinfo[] = {
@ -102,7 +107,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
32
},
{AccessMethodRelationId, /* AMNAME */
AmNameIndexId,
0,
@ -112,7 +119,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
4
},
{AccessMethodRelationId, /* AMOID */
AmOidIndexId,
0,
@ -122,7 +131,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
4
},
{AccessMethodOperatorRelationId, /* AMOPOPID */
AccessMethodOperatorIndexId,
0,
@ -132,7 +143,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_amop_amopclaid,
0,
0
}},
},
64
},
{AccessMethodOperatorRelationId, /* AMOPSTRATEGY */
AccessMethodStrategyIndexId,
0,
@ -142,7 +155,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_amop_amopsubtype,
Anum_pg_amop_amopstrategy,
0
}},
},
64
},
{AccessMethodProcedureRelationId, /* AMPROCNUM */
AccessMethodProcedureIndexId,
0,
@ -152,7 +167,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_amproc_amprocsubtype,
Anum_pg_amproc_amprocnum,
0
}},
},
64
},
{AttributeRelationId, /* ATTNAME */
AttributeRelidNameIndexId,
Anum_pg_attribute_attrelid,
@ -162,7 +179,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_attribute_attname,
0,
0
}},
},
2048
},
{AttributeRelationId, /* ATTNUM */
AttributeRelidNumIndexId,
Anum_pg_attribute_attrelid,
@ -172,7 +191,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_attribute_attnum,
0,
0
}},
},
2048
},
{AuthMemRelationId, /* AUTHMEMMEMROLE */
AuthMemMemRoleIndexId,
0,
@ -182,7 +203,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_auth_members_roleid,
0,
0
}},
},
128
},
{AuthMemRelationId, /* AUTHMEMROLEMEM */
AuthMemRoleMemIndexId,
0,
@ -192,7 +215,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_auth_members_member,
0,
0
}},
},
128
},
{AuthIdRelationId, /* AUTHNAME */
AuthIdRolnameIndexId,
0,
@ -202,7 +227,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
128
},
{AuthIdRelationId, /* AUTHOID */
AuthIdOidIndexId,
0,
@ -212,7 +239,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
128
},
{
CastRelationId, /* CASTSOURCETARGET */
CastSourceTargetIndexId,
@ -223,7 +252,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_cast_casttarget,
0,
0
}},
},
256
},
{OperatorClassRelationId, /* CLAAMNAMENSP */
OpclassAmNameNspIndexId,
0,
@ -233,7 +264,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_opclass_opcname,
Anum_pg_opclass_opcnamespace,
0
}},
},
64
},
{OperatorClassRelationId, /* CLAOID */
OpclassOidIndexId,
0,
@ -243,7 +276,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
64
},
{ConversionRelationId, /* CONDEFAULT */
ConversionDefaultIndexId,
0,
@ -253,7 +288,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_conversion_conforencoding,
Anum_pg_conversion_contoencoding,
ObjectIdAttributeNumber,
}},
},
128
},
{ConversionRelationId, /* CONNAMENSP */
ConversionNameNspIndexId,
0,
@ -263,7 +300,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_conversion_connamespace,
0,
0
}},
},
128
},
{ConversionRelationId, /* CONOID */
ConversionOidIndexId,
0,
@ -273,7 +312,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
128
},
{DatabaseRelationId, /* DATABASEOID */
DatabaseOidIndexId,
0,
@ -283,7 +324,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
4
},
{IndexRelationId, /* INDEXRELID */
IndexRelidIndexId,
Anum_pg_index_indrelid,
@ -293,7 +336,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
1024
},
{InheritsRelationId, /* INHRELID */
InheritsRelidSeqnoIndexId,
Anum_pg_inherits_inhrelid,
@ -303,7 +348,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_inherits_inhseqno,
0,
0
}},
},
256
},
{LanguageRelationId, /* LANGNAME */
LanguageNameIndexId,
0,
@ -313,7 +360,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
4
},
{LanguageRelationId, /* LANGOID */
LanguageOidIndexId,
0,
@ -323,7 +372,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
4
},
{NamespaceRelationId, /* NAMESPACENAME */
NamespaceNameIndexId,
0,
@ -333,7 +384,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
256
},
{NamespaceRelationId, /* NAMESPACEOID */
NamespaceOidIndexId,
0,
@ -343,7 +396,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
256
},
{OperatorRelationId, /* OPERNAMENSP */
OperatorNameNspIndexId,
0,
@ -353,7 +408,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_operator_oprleft,
Anum_pg_operator_oprright,
Anum_pg_operator_oprnamespace
}},
},
1024
},
{OperatorRelationId, /* OPEROID */
OperatorOidIndexId,
0,
@ -363,7 +420,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
1024
},
{ProcedureRelationId, /* PROCNAMEARGSNSP */
ProcedureNameArgsNspIndexId,
0,
@ -373,7 +432,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_proc_proargtypes,
Anum_pg_proc_pronamespace,
0
}},
},
2048
},
{ProcedureRelationId, /* PROCOID */
ProcedureOidIndexId,
0,
@ -383,7 +444,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
2048
},
{RelationRelationId, /* RELNAMENSP */
ClassNameNspIndexId,
ObjectIdAttributeNumber,
@ -393,7 +456,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_class_relnamespace,
0,
0
}},
},
1024
},
{RelationRelationId, /* RELOID */
ClassOidIndexId,
ObjectIdAttributeNumber,
@ -403,7 +468,9 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}},
},
1024
},
{RewriteRelationId, /* RULERELNAME */
RewriteRelRulenameIndexId,
Anum_pg_rewrite_ev_class,
@ -413,7 +480,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_rewrite_rulename,
0,
0
}},
},
1024
},
{StatisticRelationId, /* STATRELATT */
StatisticRelidAttnumIndexId,
Anum_pg_statistic_starelid,
@ -423,7 +492,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_statistic_staattnum,
0,
0
}},
},
1024
},
{TypeRelationId, /* TYPENAMENSP */
TypeNameNspIndexId,
Anum_pg_type_typrelid,
@ -433,7 +504,9 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_type_typnamespace,
0,
0
}},
},
1024
},
{TypeRelationId, /* TYPEOID */
TypeOidIndexId,
Anum_pg_type_typrelid,
@ -443,11 +516,12 @@ static const struct cachedesc cacheinfo[] = {
0,
0,
0
}}
},
1024
}
};
static CatCache *SysCache[
lengthof(cacheinfo)];
static CatCache *SysCache[lengthof(cacheinfo)];
static int SysCacheSize = lengthof(cacheinfo);
static bool CacheInitialized = false;
@ -476,7 +550,8 @@ InitCatalogCache(void)
cacheinfo[cacheId].indoid,
cacheinfo[cacheId].reloidattr,
cacheinfo[cacheId].nkeys,
cacheinfo[cacheId].key);
cacheinfo[cacheId].key,
cacheinfo[cacheId].nbuckets);
if (!PointerIsValid(SysCache[cacheId]))
elog(ERROR, "could not initialize cache %u (%d)",
cacheinfo[cacheId].reloid, cacheId);

View File

@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/catcache.h,v 1.58 2006/03/05 15:59:07 momjian Exp $
* $PostgreSQL: pgsql/src/include/utils/catcache.h,v 1.59 2006/06/15 02:08:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -60,7 +60,6 @@ typedef struct catcache
* searches, each of which will result in loading a negative entry
*/
long cc_invals; /* # of entries invalidated from cache */
long cc_discards; /* # of entries discarded due to overflow */
long cc_lsearches; /* total # list-searches */
long cc_lhits; /* # of matches against existing lists */
#endif
@ -75,11 +74,10 @@ typedef struct catctup
CatCache *my_cache; /* link to owning catcache */
/*
* Each tuple in a cache is a member of two Dllists: one lists all the
* elements in all the caches in LRU order, and the other lists just the
* elements in one hashbucket of one cache, also in LRU order.
* Each tuple in a cache is a member of a Dllist that stores the elements
* of its hash bucket. We keep each Dllist in LRU order to speed repeated
* lookups.
*/
Dlelem lrulist_elem; /* list member of global LRU list */
Dlelem cache_elem; /* list member of per-bucket list */
/*
@ -125,9 +123,8 @@ typedef struct catclist
* table rows satisfying the partial key. (Note: none of these will be
* negative cache entries.)
*
* A CatCList is only a member of a per-cache list; we do not do separate
* LRU management for CatCLists. See CatalogCacheCleanup() for the
* details of the management algorithm.
* A CatCList is only a member of a per-cache list; we do not currently
* divide them into hash buckets.
*
* A list marked "dead" must not be returned by subsequent searches.
* However, it won't be physically deleted from the cache until its
@ -143,7 +140,6 @@ typedef struct catclist
int refcount; /* number of active references */
bool dead; /* dead but not yet removed? */
bool ordered; /* members listed in index order? */
bool touched; /* used since last CatalogCacheCleanup? */
short nkeys; /* number of lookup keys specified */
uint32 hash_value; /* hash value for lookup keys */
HeapTupleData tuple; /* header for tuple holding keys */
@ -156,8 +152,6 @@ typedef struct catcacheheader
{
CatCache *ch_caches; /* head of list of CatCache structs */
int ch_ntup; /* # of tuples in all caches */
int ch_maxtup; /* max # of tuples allowed (LRU) */
Dllist ch_lrulist; /* overall LRU list, most recent first */
} CatCacheHeader;
@ -169,7 +163,8 @@ extern void AtEOXact_CatCache(bool isCommit);
extern CatCache *InitCatCache(int id, Oid reloid, Oid indexoid,
int reloidattr,
int nkeys, const int *key);
int nkeys, const int *key,
int nbuckets);
extern void InitCatCachePhase2(CatCache *cache);
extern HeapTuple SearchCatCache(CatCache *cache,