diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2010-11-29 12:29:42 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2010-11-29 12:30:43 -0500 |
commit | c0b5fac7010fa3468577d3a90ee8783639500fed (patch) | |
tree | 0c49a5abb23a8dcc62790fd5d9cd9d39a210f91b /src/backend/utils/cache/relcache.c | |
parent | 3c42efceb21b8dfe1b5686bd914520980933fcd4 (diff) | |
download | postgresql-c0b5fac7010fa3468577d3a90ee8783639500fed.tar.gz postgresql-c0b5fac7010fa3468577d3a90ee8783639500fed.zip |
Simplify and speed up mapping of index opfamilies to pathkeys.
Formerly we looked up the operators associated with each index (caching
them in relcache) and then the planner looked up the btree opfamily
containing such operators in order to build the btree-centric pathkey
representation that describes the index's sort order. This is quite
pointless for btree indexes: we might as well just use the index's opfamily
information directly. That saves syscache lookup cycles during planning,
and furthermore allows us to eliminate the relcache's caching of operators
altogether, which may help in reducing backend startup time.
I added code to plancat.c to perform the same type of double lookup
on-the-fly if it's ever faced with a non-btree amcanorder index AM.
If such a thing actually becomes interesting for production, we should
replace that logic with some more-direct method for identifying the
corresponding btree opfamily; but it's not worth spending effort on now.
There is considerably more to do pursuant to my recent proposal to get rid
of sort-operator-based representations of sort orderings, but this patch
grabs some of the low-hanging fruit. I'll look at the remainder of that
work after the current commitfest.
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r-- | src/backend/utils/cache/relcache.c | 137 |
1 files changed, 21 insertions, 116 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 9353a347bcb..8df12a14243 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -39,7 +39,6 @@ #include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/namespace.h" -#include "catalog/pg_amop.h" #include "catalog/pg_amproc.h" #include "catalog/pg_attrdef.h" #include "catalog/pg_authid.h" @@ -48,7 +47,6 @@ #include "catalog/pg_database.h" #include "catalog/pg_namespace.h" #include "catalog/pg_opclass.h" -#include "catalog/pg_operator.h" #include "catalog/pg_proc.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_tablespace.h" @@ -84,10 +82,10 @@ */ #define RELCACHE_INIT_FILENAME "pg_internal.init" -#define RELCACHE_INIT_FILEMAGIC 0x573265 /* version ID value */ +#define RELCACHE_INIT_FILEMAGIC 0x573266 /* version ID value */ /* - * hardcoded tuple descriptors, generated by genbki.pl + * hardcoded tuple descriptors, contents generated by genbki.pl */ static const FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class}; static const FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute}; @@ -185,19 +183,17 @@ do { \ /* * Special cache for opclass-related information * - * Note: only default operators and support procs get cached, ie, those with + * Note: only default support procs get cached, ie, those with * lefttype = righttype = opcintype. */ typedef struct opclasscacheent { Oid opclassoid; /* lookup key: OID of opclass */ bool valid; /* set TRUE after successful fill-in */ - StrategyNumber numStrats; /* max # of strategies (from pg_am) */ StrategyNumber numSupport; /* max # of support procs (from pg_am) */ Oid opcfamily; /* OID of opclass's family */ Oid opcintype; /* OID of opclass's declared input type */ - Oid *operatorOids; /* strategy operators' OIDs */ - RegProcedure *supportProcs; /* support procs */ + RegProcedure *supportProcs; /* OIDs of support procedures */ } OpClassCacheEnt; static HTAB *OpClassCache = NULL; @@ -231,15 +227,12 @@ static void AttrDefaultFetch(Relation relation); static void CheckConstraintFetch(Relation relation); static List *insert_ordered_oid(List *list, Oid datum); static void IndexSupportInitialize(oidvector *indclass, - Oid *indexOperator, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, - StrategyNumber maxStrategyNumber, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber); static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid, - StrategyNumber numStrats, StrategyNumber numSupport); static void RelationCacheInitFileRemoveInDir(const char *tblspcpath); static void unlink_initfile(const char *initfilename); @@ -980,7 +973,6 @@ RelationInitIndexAccessInfo(Relation relation) MemoryContext indexcxt; MemoryContext oldcontext; int natts; - uint16 amstrategies; uint16 amsupport; /* @@ -1015,7 +1007,6 @@ RelationInitIndexAccessInfo(Relation relation) if (natts != relation->rd_index->indnatts) elog(ERROR, "relnatts disagrees with indnatts for index %u", RelationGetRelid(relation)); - amstrategies = aform->amstrategies; amsupport = aform->amsupport; /* @@ -1044,13 +1035,6 @@ RelationInitIndexAccessInfo(Relation relation) relation->rd_opcintype = (Oid *) MemoryContextAllocZero(indexcxt, natts * sizeof(Oid)); - if (amstrategies > 0) - relation->rd_operator = (Oid *) - MemoryContextAllocZero(indexcxt, - natts * amstrategies * sizeof(Oid)); - else - relation->rd_operator = NULL; - if (amsupport > 0) { int nsupport = natts * amsupport; @@ -1082,14 +1066,13 @@ RelationInitIndexAccessInfo(Relation relation) indclass = (oidvector *) DatumGetPointer(indclassDatum); /* - * Fill the operator and support procedure OID arrays, as well as the info - * about opfamilies and opclass input types. (aminfo and supportinfo are - * left as zeroes, and are filled on-the-fly when used) + * Fill the support procedure OID array, as well as the info about + * opfamilies and opclass input types. (aminfo and supportinfo are left + * as zeroes, and are filled on-the-fly when used) */ - IndexSupportInitialize(indclass, - relation->rd_operator, relation->rd_support, + IndexSupportInitialize(indclass, relation->rd_support, relation->rd_opfamily, relation->rd_opcintype, - amstrategies, amsupport, natts); + amsupport, natts); /* * Similarly extract indoption and copy it to the cache entry @@ -1118,22 +1101,19 @@ RelationInitIndexAccessInfo(Relation relation) * Initializes an index's cached opclass information, * given the index's pg_index.indclass entry. * - * Data is returned into *indexOperator, *indexSupport, *opFamily, and - * *opcInType, which are arrays allocated by the caller. + * Data is returned into *indexSupport, *opFamily, and *opcInType, + * which are arrays allocated by the caller. * - * The caller also passes maxStrategyNumber, maxSupportNumber, and - * maxAttributeNumber, since these indicate the size of the arrays - * it has allocated --- but in practice these numbers must always match - * those obtainable from the system catalog entries for the index and - * access method. + * The caller also passes maxSupportNumber and maxAttributeNumber, since these + * indicate the size of the arrays it has allocated --- but in practice these + * numbers must always match those obtainable from the system catalog entries + * for the index and access method. */ static void IndexSupportInitialize(oidvector *indclass, - Oid *indexOperator, RegProcedure *indexSupport, Oid *opFamily, Oid *opcInType, - StrategyNumber maxStrategyNumber, StrategyNumber maxSupportNumber, AttrNumber maxAttributeNumber) { @@ -1148,16 +1128,11 @@ IndexSupportInitialize(oidvector *indclass, /* look up the info for this opclass, using a cache */ opcentry = LookupOpclassInfo(indclass->values[attIndex], - maxStrategyNumber, maxSupportNumber); /* copy cached data into relcache entry */ opFamily[attIndex] = opcentry->opcfamily; opcInType[attIndex] = opcentry->opcintype; - if (maxStrategyNumber > 0) - memcpy(&indexOperator[attIndex * maxStrategyNumber], - opcentry->operatorOids, - maxStrategyNumber * sizeof(Oid)); if (maxSupportNumber > 0) memcpy(&indexSupport[attIndex * maxSupportNumber], opcentry->supportProcs, @@ -1171,9 +1146,9 @@ IndexSupportInitialize(oidvector *indclass, * This routine maintains a per-opclass cache of the information needed * by IndexSupportInitialize(). This is more efficient than relying on * the catalog cache, because we can load all the info about a particular - * opclass in a single indexscan of pg_amproc or pg_amop. + * opclass in a single indexscan of pg_amproc. * - * The information from pg_am about expected range of strategy and support + * The information from pg_am about expected range of support function * numbers is passed in, rather than being looked up, mainly because the * caller will have it already. * @@ -1187,7 +1162,6 @@ IndexSupportInitialize(oidvector *indclass, */ static OpClassCacheEnt * LookupOpclassInfo(Oid operatorClassOid, - StrategyNumber numStrats, StrategyNumber numSupport) { OpClassCacheEnt *opcentry; @@ -1223,16 +1197,8 @@ LookupOpclassInfo(Oid operatorClassOid, { /* Need to allocate memory for new entry */ opcentry->valid = false; /* until known OK */ - opcentry->numStrats = numStrats; opcentry->numSupport = numSupport; - if (numStrats > 0) - opcentry->operatorOids = (Oid *) - MemoryContextAllocZero(CacheMemoryContext, - numStrats * sizeof(Oid)); - else - opcentry->operatorOids = NULL; - if (numSupport > 0) opcentry->supportProcs = (RegProcedure *) MemoryContextAllocZero(CacheMemoryContext, @@ -1242,7 +1208,6 @@ LookupOpclassInfo(Oid operatorClassOid, } else { - Assert(numStrats == opcentry->numStrats); Assert(numSupport == opcentry->numSupport); } @@ -1273,7 +1238,7 @@ LookupOpclassInfo(Oid operatorClassOid, /* * We have to fetch the pg_opclass row to determine its opfamily and - * opcintype, which are needed to look up the operators and functions. + * opcintype, which are needed to look up related operators and functions. * It'd be convenient to use the syscache here, but that probably doesn't * work while bootstrapping. */ @@ -1298,45 +1263,6 @@ LookupOpclassInfo(Oid operatorClassOid, systable_endscan(scan); heap_close(rel, AccessShareLock); - - /* - * Scan pg_amop to obtain operators for the opclass. We only fetch the - * default ones (those with lefttype = righttype = opcintype). - */ - if (numStrats > 0) - { - ScanKeyInit(&skey[0], - Anum_pg_amop_amopfamily, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(opcentry->opcfamily)); - ScanKeyInit(&skey[1], - Anum_pg_amop_amoplefttype, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(opcentry->opcintype)); - ScanKeyInit(&skey[2], - Anum_pg_amop_amoprighttype, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(opcentry->opcintype)); - rel = heap_open(AccessMethodOperatorRelationId, AccessShareLock); - scan = systable_beginscan(rel, AccessMethodStrategyIndexId, indexOK, - SnapshotNow, 3, skey); - - while (HeapTupleIsValid(htup = systable_getnext(scan))) - { - Form_pg_amop amopform = (Form_pg_amop) GETSTRUCT(htup); - - if (amopform->amopstrategy <= 0 || - (StrategyNumber) amopform->amopstrategy > numStrats) - elog(ERROR, "invalid amopstrategy number %d for opclass %u", - amopform->amopstrategy, operatorClassOid); - opcentry->operatorOids[amopform->amopstrategy - 1] = - amopform->amopopr; - } - - systable_endscan(scan); - heap_close(rel, AccessShareLock); - } - /* * Scan pg_amproc to obtain support procs for the opclass. We only fetch * the default ones (those with lefttype = righttype = opcintype). @@ -2907,18 +2833,14 @@ RelationCacheInitializePhase3(void) IndexRelationId); load_critical_index(OpclassOidIndexId, OperatorClassRelationId); - load_critical_index(AccessMethodStrategyIndexId, - AccessMethodOperatorRelationId); load_critical_index(AccessMethodProcedureIndexId, AccessMethodProcedureRelationId); - load_critical_index(OperatorOidIndexId, - OperatorRelationId); load_critical_index(RewriteRelRulenameIndexId, RewriteRelationId); load_critical_index(TriggerRelidNameIndexId, TriggerRelationId); -#define NUM_CRITICAL_LOCAL_INDEXES 9 /* fix if you change list above */ +#define NUM_CRITICAL_LOCAL_INDEXES 7 /* fix if you change list above */ criticalRelcachesBuilt = true; } @@ -4044,7 +3966,6 @@ load_relcache_init_file(bool shared) MemoryContext indexcxt; Oid *opfamily; Oid *opcintype; - Oid *operator; RegProcedure *support; int nsupport; int16 *indoption; @@ -4105,17 +4026,7 @@ load_relcache_init_file(bool shared) rel->rd_opcintype = opcintype; - /* next, read the vector of operator OIDs */ - if (fread(&len, 1, sizeof(len), fp) != sizeof(len)) - goto read_failed; - - operator = (Oid *) MemoryContextAlloc(indexcxt, len); - if (fread(operator, 1, len, fp) != len) - goto read_failed; - - rel->rd_operator = operator; - - /* next, read the vector of support procedures */ + /* next, read the vector of support procedure OIDs */ if (fread(&len, 1, sizeof(len), fp) != sizeof(len)) goto read_failed; support = (RegProcedure *) MemoryContextAlloc(indexcxt, len); @@ -4154,7 +4065,6 @@ load_relcache_init_file(bool shared) Assert(rel->rd_aminfo == NULL); Assert(rel->rd_opfamily == NULL); Assert(rel->rd_opcintype == NULL); - Assert(rel->rd_operator == NULL); Assert(rel->rd_support == NULL); Assert(rel->rd_supportinfo == NULL); Assert(rel->rd_indoption == NULL); @@ -4371,12 +4281,7 @@ write_relcache_init_file(bool shared) relform->relnatts * sizeof(Oid), fp); - /* next, write the vector of operator OIDs */ - write_item(rel->rd_operator, - relform->relnatts * (am->amstrategies * sizeof(Oid)), - fp); - - /* next, write the vector of support procedures */ + /* next, write the vector of support procedure OIDs */ write_item(rel->rd_support, relform->relnatts * (am->amsupport * sizeof(RegProcedure)), fp); |