Make catalog cache hash tables resizeable.

If the hash table backing a catalog cache becomes too full (fillfactor > 2),
enlarge it. A new buckets array, double the size of the old, is allocated,
and all entries in the old hash are moved to the right bucket in the new
hash.

This has two benefits. First, cache lookups don't get so expensive when
there are lots of entries in a cache, like if you access hundreds of
thousands of tables. Second, we can make the (initial) sizes of the caches
much smaller, which saves memory.

This patch dials down the initial sizes of the catcaches. The new sizes are
chosen so that a backend that only runs a few basic queries still won't need
to enlarge any of them.
This commit is contained in:
Heikki Linnakangas 2013-09-05 19:47:56 +03:00
parent b1892aaeaa
commit 20cb18db46
3 changed files with 102 additions and 58 deletions

View File

@ -734,9 +734,8 @@ InitCatCache(int id,
int i; int i;
/* /*
* nbuckets is the number of hash buckets to use in this catcache. * nbuckets is the initial number of hash buckets to use in this catcache.
* Currently we just use a hard-wired estimate of an appropriate size for * It will be enlarged later if it becomes too full.
* each cache; maybe later make them dynamically resizable?
* *
* nbuckets must be a power of two. We check this via Assert rather than * 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 * a full runtime check because the values will be coming from constant
@ -775,7 +774,8 @@ InitCatCache(int id,
* *
* Note: we rely on zeroing to initialize all the dlist headers correctly * Note: we rely on zeroing to initialize all the dlist headers correctly
*/ */
cp = (CatCache *) palloc0(sizeof(CatCache) + nbuckets * sizeof(dlist_head)); cp = (CatCache *) palloc0(sizeof(CatCache));
cp->cc_bucket = palloc0(nbuckets * sizeof(dlist_head));
/* /*
* initialize the cache's relation information for the relation * initialize the cache's relation information for the relation
@ -813,6 +813,43 @@ InitCatCache(int id,
return cp; return cp;
} }
/*
* Enlarge a catcache, doubling the number of buckets.
*/
static void
RehashCatCache(CatCache *cp)
{
dlist_head *newbucket;
int newnbuckets;
int i;
elog(DEBUG1, "rehashing catalog cache id %d for %s; %d tups, %d buckets",
cp->id, cp->cc_relname, cp->cc_ntup, cp->cc_nbuckets);
/* Allocate a new, larger, hash table. */
newnbuckets = cp->cc_nbuckets * 2;
newbucket = (dlist_head *) MemoryContextAllocZero(CacheMemoryContext, newnbuckets * sizeof(dlist_head));
/* Move all entries from old hash table to new. */
for (i = 0; i < cp->cc_nbuckets; i++)
{
dlist_mutable_iter iter;
dlist_foreach_modify(iter, &cp->cc_bucket[i])
{
CatCTup *ct = dlist_container(CatCTup, cache_elem, iter.cur);
int hashIndex = HASH_INDEX(ct->hash_value, newnbuckets);
dlist_delete(iter.cur);
dlist_push_head(&newbucket[hashIndex], &ct->cache_elem);
}
}
/* Switch to the new array. */
pfree(cp->cc_bucket);
cp->cc_nbuckets = newnbuckets;
cp->cc_bucket = newbucket;
}
/* /*
* CatalogCacheInitializeCache * CatalogCacheInitializeCache
* *
@ -1684,6 +1721,13 @@ CatalogCacheCreateEntry(CatCache *cache, HeapTuple ntp,
cache->cc_ntup++; cache->cc_ntup++;
CacheHdr->ch_ntup++; CacheHdr->ch_ntup++;
/*
* If the hash table has become too full, enlarge the buckets array.
* Quite arbitrarily, we enlarge when fill factor > 2.
*/
if (cache->cc_ntup > cache->cc_nbuckets * 2)
RehashCatCache(cache);
return ct; return ct;
} }

View File

@ -122,7 +122,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
32 16
}, },
{AccessMethodRelationId, /* AMNAME */ {AccessMethodRelationId, /* AMNAME */
AmNameIndexId, AmNameIndexId,
@ -177,7 +177,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_amproc_amprocrighttype, Anum_pg_amproc_amprocrighttype,
Anum_pg_amproc_amprocnum Anum_pg_amproc_amprocnum
}, },
64 16
}, },
{AttributeRelationId, /* ATTNAME */ {AttributeRelationId, /* ATTNAME */
AttributeRelidNameIndexId, AttributeRelidNameIndexId,
@ -188,7 +188,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
2048 32
}, },
{AttributeRelationId, /* ATTNUM */ {AttributeRelationId, /* ATTNUM */
AttributeRelidNumIndexId, AttributeRelidNumIndexId,
@ -199,7 +199,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
2048 128
}, },
{AuthMemRelationId, /* AUTHMEMMEMROLE */ {AuthMemRelationId, /* AUTHMEMMEMROLE */
AuthMemMemRoleIndexId, AuthMemMemRoleIndexId,
@ -210,7 +210,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
128 8
}, },
{AuthMemRelationId, /* AUTHMEMROLEMEM */ {AuthMemRelationId, /* AUTHMEMROLEMEM */
AuthMemRoleMemIndexId, AuthMemRoleMemIndexId,
@ -221,7 +221,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
128 8
}, },
{AuthIdRelationId, /* AUTHNAME */ {AuthIdRelationId, /* AUTHNAME */
AuthIdRolnameIndexId, AuthIdRolnameIndexId,
@ -232,7 +232,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
128 8
}, },
{AuthIdRelationId, /* AUTHOID */ {AuthIdRelationId, /* AUTHOID */
AuthIdOidIndexId, AuthIdOidIndexId,
@ -243,7 +243,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
128 8
}, },
{ {
CastRelationId, /* CASTSOURCETARGET */ CastRelationId, /* CASTSOURCETARGET */
@ -266,7 +266,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_opclass_opcnamespace, Anum_pg_opclass_opcnamespace,
0 0
}, },
64 8
}, },
{OperatorClassRelationId, /* CLAOID */ {OperatorClassRelationId, /* CLAOID */
OpclassOidIndexId, OpclassOidIndexId,
@ -277,7 +277,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
64 8
}, },
{CollationRelationId, /* COLLNAMEENCNSP */ {CollationRelationId, /* COLLNAMEENCNSP */
CollationNameEncNspIndexId, CollationNameEncNspIndexId,
@ -288,7 +288,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_collation_collnamespace, Anum_pg_collation_collnamespace,
0 0
}, },
64 8
}, },
{CollationRelationId, /* COLLOID */ {CollationRelationId, /* COLLOID */
CollationOidIndexId, CollationOidIndexId,
@ -299,7 +299,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
64 8
}, },
{ConversionRelationId, /* CONDEFAULT */ {ConversionRelationId, /* CONDEFAULT */
ConversionDefaultIndexId, ConversionDefaultIndexId,
@ -310,7 +310,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_conversion_contoencoding, Anum_pg_conversion_contoencoding,
ObjectIdAttributeNumber, ObjectIdAttributeNumber,
}, },
128 8
}, },
{ConversionRelationId, /* CONNAMENSP */ {ConversionRelationId, /* CONNAMENSP */
ConversionNameNspIndexId, ConversionNameNspIndexId,
@ -321,7 +321,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
128 8
}, },
{ConstraintRelationId, /* CONSTROID */ {ConstraintRelationId, /* CONSTROID */
ConstraintOidIndexId, ConstraintOidIndexId,
@ -332,7 +332,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
1024 16
}, },
{ConversionRelationId, /* CONVOID */ {ConversionRelationId, /* CONVOID */
ConversionOidIndexId, ConversionOidIndexId,
@ -343,7 +343,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
128 8
}, },
{DatabaseRelationId, /* DATABASEOID */ {DatabaseRelationId, /* DATABASEOID */
DatabaseOidIndexId, DatabaseOidIndexId,
@ -365,7 +365,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_default_acl_defaclobjtype, Anum_pg_default_acl_defaclobjtype,
0 0
}, },
256 8
}, },
{EnumRelationId, /* ENUMOID */ {EnumRelationId, /* ENUMOID */
EnumOidIndexId, EnumOidIndexId,
@ -376,7 +376,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
256 8
}, },
{EnumRelationId, /* ENUMTYPOIDNAME */ {EnumRelationId, /* ENUMTYPOIDNAME */
EnumTypIdLabelIndexId, EnumTypIdLabelIndexId,
@ -387,7 +387,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
256 8
}, },
{EventTriggerRelationId, /* EVENTTRIGGERNAME */ {EventTriggerRelationId, /* EVENTTRIGGERNAME */
EventTriggerNameIndexId, EventTriggerNameIndexId,
@ -420,7 +420,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
8 2
}, },
{ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPEROID */ {ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPEROID */
ForeignDataWrapperOidIndexId, ForeignDataWrapperOidIndexId,
@ -431,7 +431,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
8 2
}, },
{ForeignServerRelationId, /* FOREIGNSERVERNAME */ {ForeignServerRelationId, /* FOREIGNSERVERNAME */
ForeignServerNameIndexId, ForeignServerNameIndexId,
@ -442,7 +442,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
32 2
}, },
{ForeignServerRelationId, /* FOREIGNSERVEROID */ {ForeignServerRelationId, /* FOREIGNSERVEROID */
ForeignServerOidIndexId, ForeignServerOidIndexId,
@ -453,7 +453,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
32 2
}, },
{ForeignTableRelationId, /* FOREIGNTABLEREL */ {ForeignTableRelationId, /* FOREIGNTABLEREL */
ForeignTableRelidIndexId, ForeignTableRelidIndexId,
@ -464,7 +464,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
128 4
}, },
{IndexRelationId, /* INDEXRELID */ {IndexRelationId, /* INDEXRELID */
IndexRelidIndexId, IndexRelidIndexId,
@ -475,7 +475,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
1024 64
}, },
{LanguageRelationId, /* LANGNAME */ {LanguageRelationId, /* LANGNAME */
LanguageNameIndexId, LanguageNameIndexId,
@ -508,7 +508,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
256 4
}, },
{NamespaceRelationId, /* NAMESPACEOID */ {NamespaceRelationId, /* NAMESPACEOID */
NamespaceOidIndexId, NamespaceOidIndexId,
@ -519,7 +519,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
256 16
}, },
{OperatorRelationId, /* OPERNAMENSP */ {OperatorRelationId, /* OPERNAMENSP */
OperatorNameNspIndexId, OperatorNameNspIndexId,
@ -530,7 +530,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_operator_oprright, Anum_pg_operator_oprright,
Anum_pg_operator_oprnamespace Anum_pg_operator_oprnamespace
}, },
1024 256
}, },
{OperatorRelationId, /* OPEROID */ {OperatorRelationId, /* OPEROID */
OperatorOidIndexId, OperatorOidIndexId,
@ -541,7 +541,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
1024 32
}, },
{OperatorFamilyRelationId, /* OPFAMILYAMNAMENSP */ {OperatorFamilyRelationId, /* OPFAMILYAMNAMENSP */
OpfamilyAmNameNspIndexId, OpfamilyAmNameNspIndexId,
@ -552,7 +552,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_opfamily_opfnamespace, Anum_pg_opfamily_opfnamespace,
0 0
}, },
64 8
}, },
{OperatorFamilyRelationId, /* OPFAMILYOID */ {OperatorFamilyRelationId, /* OPFAMILYOID */
OpfamilyOidIndexId, OpfamilyOidIndexId,
@ -563,7 +563,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
64 8
}, },
{ProcedureRelationId, /* PROCNAMEARGSNSP */ {ProcedureRelationId, /* PROCNAMEARGSNSP */
ProcedureNameArgsNspIndexId, ProcedureNameArgsNspIndexId,
@ -574,7 +574,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_proc_pronamespace, Anum_pg_proc_pronamespace,
0 0
}, },
2048 128
}, },
{ProcedureRelationId, /* PROCOID */ {ProcedureRelationId, /* PROCOID */
ProcedureOidIndexId, ProcedureOidIndexId,
@ -585,7 +585,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
2048 128
}, },
{RangeRelationId, /* RANGETYPE */ {RangeRelationId, /* RANGETYPE */
RangeTypidIndexId, RangeTypidIndexId,
@ -596,7 +596,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
64 4
}, },
{RelationRelationId, /* RELNAMENSP */ {RelationRelationId, /* RELNAMENSP */
ClassNameNspIndexId, ClassNameNspIndexId,
@ -607,7 +607,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
1024 128
}, },
{RelationRelationId, /* RELOID */ {RelationRelationId, /* RELOID */
ClassOidIndexId, ClassOidIndexId,
@ -618,7 +618,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
1024 128
}, },
{RewriteRelationId, /* RULERELNAME */ {RewriteRelationId, /* RULERELNAME */
RewriteRelRulenameIndexId, RewriteRelRulenameIndexId,
@ -629,7 +629,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
1024 8
}, },
{StatisticRelationId, /* STATRELATTINH */ {StatisticRelationId, /* STATRELATTINH */
StatisticRelidAttnumInhIndexId, StatisticRelidAttnumInhIndexId,
@ -640,7 +640,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_statistic_stainherit, Anum_pg_statistic_stainherit,
0 0
}, },
1024 128
}, },
{TableSpaceRelationId, /* TABLESPACEOID */ {TableSpaceRelationId, /* TABLESPACEOID */
TablespaceOidIndexId, TablespaceOidIndexId,
@ -651,7 +651,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0, 0,
}, },
16 4
}, },
{TSConfigMapRelationId, /* TSCONFIGMAP */ {TSConfigMapRelationId, /* TSCONFIGMAP */
TSConfigMapIndexId, TSConfigMapIndexId,
@ -662,7 +662,7 @@ static const struct cachedesc cacheinfo[] = {
Anum_pg_ts_config_map_mapseqno, Anum_pg_ts_config_map_mapseqno,
0 0
}, },
4 2
}, },
{TSConfigRelationId, /* TSCONFIGNAMENSP */ {TSConfigRelationId, /* TSCONFIGNAMENSP */
TSConfigNameNspIndexId, TSConfigNameNspIndexId,
@ -673,7 +673,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
16 2
}, },
{TSConfigRelationId, /* TSCONFIGOID */ {TSConfigRelationId, /* TSCONFIGOID */
TSConfigOidIndexId, TSConfigOidIndexId,
@ -684,7 +684,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
16 2
}, },
{TSDictionaryRelationId, /* TSDICTNAMENSP */ {TSDictionaryRelationId, /* TSDICTNAMENSP */
TSDictionaryNameNspIndexId, TSDictionaryNameNspIndexId,
@ -695,7 +695,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
16 2
}, },
{TSDictionaryRelationId, /* TSDICTOID */ {TSDictionaryRelationId, /* TSDICTOID */
TSDictionaryOidIndexId, TSDictionaryOidIndexId,
@ -706,7 +706,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
16 2
}, },
{TSParserRelationId, /* TSPARSERNAMENSP */ {TSParserRelationId, /* TSPARSERNAMENSP */
TSParserNameNspIndexId, TSParserNameNspIndexId,
@ -717,7 +717,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
4 2
}, },
{TSParserRelationId, /* TSPARSEROID */ {TSParserRelationId, /* TSPARSEROID */
TSParserOidIndexId, TSParserOidIndexId,
@ -728,7 +728,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
4 2
}, },
{TSTemplateRelationId, /* TSTEMPLATENAMENSP */ {TSTemplateRelationId, /* TSTEMPLATENAMENSP */
TSTemplateNameNspIndexId, TSTemplateNameNspIndexId,
@ -739,7 +739,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
16 2
}, },
{TSTemplateRelationId, /* TSTEMPLATEOID */ {TSTemplateRelationId, /* TSTEMPLATEOID */
TSTemplateOidIndexId, TSTemplateOidIndexId,
@ -750,7 +750,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
16 2
}, },
{TypeRelationId, /* TYPENAMENSP */ {TypeRelationId, /* TYPENAMENSP */
TypeNameNspIndexId, TypeNameNspIndexId,
@ -761,7 +761,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
1024 64
}, },
{TypeRelationId, /* TYPEOID */ {TypeRelationId, /* TYPEOID */
TypeOidIndexId, TypeOidIndexId,
@ -772,7 +772,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
1024 64
}, },
{UserMappingRelationId, /* USERMAPPINGOID */ {UserMappingRelationId, /* USERMAPPINGOID */
UserMappingOidIndexId, UserMappingOidIndexId,
@ -783,7 +783,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
128 2
}, },
{UserMappingRelationId, /* USERMAPPINGUSERSERVER */ {UserMappingRelationId, /* USERMAPPINGUSERSERVER */
UserMappingUserServerIndexId, UserMappingUserServerIndexId,
@ -794,7 +794,7 @@ static const struct cachedesc cacheinfo[] = {
0, 0,
0 0
}, },
128 2
} }
}; };

View File

@ -66,8 +66,8 @@ typedef struct catcache
long cc_lsearches; /* total # list-searches */ long cc_lsearches; /* total # list-searches */
long cc_lhits; /* # of matches against existing lists */ long cc_lhits; /* # of matches against existing lists */
#endif #endif
dlist_head cc_bucket[1]; /* hash buckets --- VARIABLE LENGTH ARRAY */ dlist_head *cc_bucket; /* hash buckets */
} CatCache; /* VARIABLE LENGTH STRUCT */ } CatCache;
typedef struct catctup typedef struct catctup