From f8fc3f6b76c48c4834117c91a13223a663210e87 Mon Sep 17 00:00:00 2001 From: amit Date: Mon, 16 Apr 2018 11:54:44 +0900 Subject: [PATCH v1 3/3] Cache partsupfunc separately from PartitionKey --- src/backend/executor/execPartition.c | 24 +++++++-- src/backend/optimizer/util/plancat.c | 9 +++- src/backend/partitioning/partbounds.c | 40 ++++++++++++--- src/backend/partitioning/partprune.c | 8 ++- src/backend/utils/cache/partcache.c | 97 +++++++++++++++++++++++++++-------- src/backend/utils/cache/relcache.c | 2 + src/include/executor/execPartition.h | 2 + src/include/partitioning/partprune.h | 2 +- src/include/utils/partcache.h | 4 +- src/include/utils/rel.h | 2 + 10 files changed, 150 insertions(+), 40 deletions(-) diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c index f04bd276ee..87ec10f6f2 100644 --- a/src/backend/executor/execPartition.c +++ b/src/backend/executor/execPartition.c @@ -894,6 +894,13 @@ get_partition_dispatch_recurse(Relation rel, Relation parent, pd->reldesc = rel; pd->key = partkey; pd->keystate = NIL; + /* Get partsupfunc FmgrInfo's. */ + for (i = 0; i < partkey->partnatts; i++) + { + fmgr_info_copy(&pd->partsupfunc[i], + partition_getprocinfo(rel, partkey, i), + CurrentMemoryContext); + } pd->nparts = nparts; pd->boundinfo = boundinfo; if (parent != NULL) @@ -1044,6 +1051,7 @@ get_partition_for_tuple(PartitionDispatch pd, Datum *values, bool *isnull) int bound_offset; int part_index = -1; PartitionKey key = pd->key; + FmgrInfo *partsupfunc = pd->partsupfunc; PartitionBoundInfo boundinfo = pd->boundinfo; /* Route as appropriate based on partitioning strategy. */ @@ -1053,7 +1061,7 @@ get_partition_for_tuple(PartitionDispatch pd, Datum *values, bool *isnull) { int greatest_modulus = get_hash_partition_greatest_modulus(boundinfo); uint64 rowHash = compute_hash_value(key->partnatts, - key->partsupfunc, + partsupfunc, values, isnull); part_index = boundinfo->indexes[rowHash % greatest_modulus]; @@ -1070,7 +1078,7 @@ get_partition_for_tuple(PartitionDispatch pd, Datum *values, bool *isnull) { bool equal = false; - bound_offset = partition_list_bsearch(key->partsupfunc, + bound_offset = partition_list_bsearch(partsupfunc, key->partcollation, boundinfo, values[0], &equal); @@ -1100,7 +1108,7 @@ get_partition_for_tuple(PartitionDispatch pd, Datum *values, bool *isnull) if (!range_partkey_has_null) { - bound_offset = partition_range_datum_bsearch(key->partsupfunc, + bound_offset = partition_range_datum_bsearch(partsupfunc, key->partcollation, boundinfo, key->partnatts, @@ -1400,6 +1408,7 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) int nparts; PartitionBoundInfo boundinfo; int partnatts; + int j; pprune->present_parts = bms_copy(pinfo->present_parts); pprune->subnode_map = palloc(sizeof(int) * pinfo->nparts); @@ -1420,7 +1429,6 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) */ rel = relation_open(pinfo->reloid, NoLock); - /* Copy data from relcache into current memory context. */ partkey = RelationGetPartitionKey(rel); nparts = RelationGetPartitionCount(rel); boundinfo = RelationGetPartitionBounds(rel); @@ -1430,7 +1438,13 @@ ExecSetupPartitionPruneState(PlanState *planstate, List *partitionpruneinfo) context->partopfamily = partkey->partopfamily; context->partopcintype = partkey->partopcintype; context->partcollation = partkey->partcollation; - context->partsupfunc = partkey->partsupfunc; + /* Get partsupfunc FmgrInfo's. */ + for (j = 0; j < partkey->partnatts; j++) + { + fmgr_info_copy(&context->partsupfunc[j], + partition_getprocinfo(rel, partkey, j), + CurrentMemoryContext); + } context->nparts = nparts; context->boundinfo = boundinfo; context->planstate = planstate; diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index cfda6f2a34..e189d07efe 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1940,7 +1940,7 @@ find_partition_scheme(PlannerInfo *root, Relation rel, */ #ifdef USE_ASSERT_CHECKING for (i = 0; i < partkey->partnatts; i++) - Assert(partkey->partsupfunc[i].fn_oid == + Assert(partkey->partsupfuncid[i] == part_scheme->partsupfunc[i].fn_oid); #endif @@ -1960,7 +1960,12 @@ find_partition_scheme(PlannerInfo *root, Relation rel, part_scheme->partcollation = partkey->partcollation; part_scheme->parttyplen = partkey->parttyplen; part_scheme->parttypbyval = partkey->parttypbyval; - part_scheme->partsupfunc = partkey->partsupfunc; + part_scheme->partsupfunc = (FmgrInfo *) + palloc(sizeof(FmgrInfo) * partnatts); + for (i = 0; i < partnatts; i++) + fmgr_info_copy(&part_scheme->partsupfunc[i], + partition_getprocinfo(rel, partkey, i), + CurrentMemoryContext); /* Add the partitioning scheme to PlannerInfo. */ root->part_schemes = lappend(root->part_schemes, part_scheme); diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c index 0d2064d617..321b7cf427 100644 --- a/src/backend/partitioning/partbounds.c +++ b/src/backend/partitioning/partbounds.c @@ -420,8 +420,15 @@ check_new_partition_bound(char *relname, Relation parent, case PARTITION_STRATEGY_LIST: { + FmgrInfo partsupfunc; + Assert(spec->strategy == PARTITION_STRATEGY_LIST); + /* Get partsupfunc FmgrInfo for the only key. */ + fmgr_info_copy(&partsupfunc, + partition_getprocinfo(parent, key, 0), + CurrentMemoryContext); + if (nparts > 0) { ListCell *cell; @@ -441,8 +448,8 @@ check_new_partition_bound(char *relname, Relation parent, int offset; bool equal; - offset = partition_list_bsearch(&key->partsupfunc[0], - key->partcollation, + offset = partition_list_bsearch(&partsupfunc, + key->partcollation, boundinfo, val->constvalue, &equal); @@ -469,6 +476,16 @@ check_new_partition_bound(char *relname, Relation parent, { PartitionRangeBound *lower, *upper; + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; + int i; + + /* Get partsupfunc FmgrInfo's. */ + for (i = 0; i < key->partnatts; i++) + { + fmgr_info_copy(&partsupfunc[i], + partition_getprocinfo(parent, key, i), + CurrentMemoryContext); + } Assert(spec->strategy == PARTITION_STRATEGY_RANGE); lower = make_one_range_bound(key, -1, spec->lowerdatums, true); @@ -478,7 +495,7 @@ check_new_partition_bound(char *relname, Relation parent, * First check if the resulting range would be empty with * specified lower and upper bounds */ - if (partition_rbound_cmp(key->partnatts, key->partsupfunc, + if (partition_rbound_cmp(key->partnatts, partsupfunc, key->partcollation, lower->datums, lower->kind, true, upper) >= 0) { @@ -518,7 +535,7 @@ check_new_partition_bound(char *relname, Relation parent, * at the end. */ offset = partition_range_bsearch(key->partnatts, - key->partsupfunc, + partsupfunc, key->partcollation, boundinfo, lower, &equal); @@ -543,7 +560,7 @@ check_new_partition_bound(char *relname, Relation parent, is_lower = (boundinfo->indexes[offset + 1] == -1); cmpval = partition_rbound_cmp(key->partnatts, - key->partsupfunc, + partsupfunc, key->partcollation, datums, kind, is_lower, upper); @@ -2150,6 +2167,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) { Relation parent; PartitionKey key; + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; int j; /* Open parent relation and fetch partition keyinfo */ @@ -2172,6 +2190,14 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) errmsg("\"%s\" is not a hash partitioned table", get_rel_name(parentId)))); + /* Get partsupfunc FmgrInfo's. */ + for (j = 0; j < key->partnatts; j++) + { + fmgr_info_copy(&partsupfunc[j], + partition_getprocinfo(parent, key, j), + CurrentMemoryContext); + } + if (!get_fn_expr_variadic(fcinfo->flinfo)) { int nargs = PG_NARGS() - 3; @@ -2204,7 +2230,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) j + 1, format_type_be(key->parttypid[j]), format_type_be(argtype)))); fmgr_info_copy(&my_extra->partsupfunc[j], - &key->partsupfunc[j], + &partsupfunc[j], fcinfo->flinfo->fn_mcxt); } @@ -2238,7 +2264,7 @@ satisfies_hash_partition(PG_FUNCTION_ARGS) format_type_be(my_extra->variadic_type)))); fmgr_info_copy(&my_extra->partsupfunc[0], - &key->partsupfunc[0], + &partsupfunc[0], fcinfo->flinfo->fn_mcxt); } diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c index f047e6e827..d506bc0264 100644 --- a/src/backend/partitioning/partprune.c +++ b/src/backend/partitioning/partprune.c @@ -436,7 +436,10 @@ prune_append_rel_partitions(RelOptInfo *rel) context.partopfamily = rel->part_scheme->partopfamily; context.partopcintype = rel->part_scheme->partopcintype; context.partcollation = rel->part_scheme->partcollation; - context.partsupfunc = rel->part_scheme->partsupfunc; + for (i = 0; i < context.partnatts; i++) + fmgr_info_copy(&context.partsupfunc[i], + &rel->part_scheme->partsupfunc[i], + CurrentMemoryContext); context.nparts = rel->nparts; context.boundinfo = rel->boundinfo; @@ -1412,7 +1415,8 @@ match_clause_to_partition_key(RelOptInfo *rel, partclause->op_is_ne = false; partclause->expr = expr; /* We know that expr is of Boolean type. */ - partclause->cmpfn = rel->part_scheme->partsupfunc[partkeyidx].fn_oid; + partclause->cmpfn = + rel->part_scheme->partsupfunc[partkeyidx].fn_oid; partclause->op_strategy = InvalidStrategy; *pc = partclause; diff --git a/src/backend/utils/cache/partcache.c b/src/backend/utils/cache/partcache.c index e234320e30..f73582a2a1 100644 --- a/src/backend/utils/cache/partcache.c +++ b/src/backend/utils/cache/partcache.c @@ -36,6 +36,12 @@ #include "utils/rel.h" #include "utils/syscache.h" +typedef struct PartitionBoundSortInfo +{ + FmgrInfo *partsupfunc; + PartitionKey key; +} PartitionBoundSortInfo; + static int32 qsort_partition_hbound_cmp(const void *a, const void *b); static int32 qsort_partition_list_value_cmp(const void *a, const void *b, void *arg); @@ -146,10 +152,16 @@ RelationBuildPartitionKey(Relation relation) key->partattrs = (AttrNumber *) palloc0(key->partnatts * sizeof(AttrNumber)); key->partopfamily = (Oid *) palloc0(key->partnatts * sizeof(Oid)); key->partopcintype = (Oid *) palloc0(key->partnatts * sizeof(Oid)); - key->partsupfunc = (FmgrInfo *) palloc0(key->partnatts * sizeof(FmgrInfo)); - + key->partsupfuncid = (Oid *) palloc0(key->partnatts * sizeof(Oid)); key->partcollation = (Oid *) palloc0(key->partnatts * sizeof(Oid)); + /* + * Also allocate space for partition support procedure FmgrInfo's, but + * they won't be filled until someone calls partition_getprocinfo. + */ + relation->rd_partsupfunc = (FmgrInfo *) + palloc0(key->partnatts * sizeof(FmgrInfo)); + /* Gather type and collation info as well */ key->parttypid = (Oid *) palloc0(key->partnatts * sizeof(Oid)); key->parttypmod = (int32 *) palloc0(key->partnatts * sizeof(int32)); @@ -199,12 +211,7 @@ RelationBuildPartitionKey(Relation relation) procnum, format_type_be(opclassform->opcintype)))); - /* - * Actually, we never use one of these FmgrInfo's without copying - * first to the caller's memory context, so setting the memory context - * here may seem pointless. - */ - fmgr_info_cxt(funcid, &key->partsupfunc[i], relation->rd_partcxt); + key->partsupfuncid[i] = funcid; /* Collation */ key->partcollation[i] = collation->values[i]; @@ -336,6 +343,20 @@ RelationBuildPartitionDesc(Relation rel) if (nparts > 0) { + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; + PartitionBoundSortInfo sortinfo; + + /* Get partsupfunc FmgrInfo's. */ + for (i = 0; i < key->partnatts; i++) + { + fmgr_info_copy(&partsupfunc[i], + partition_getprocinfo(rel, key, i), + CurrentMemoryContext); + } + + sortinfo.partsupfunc = partsupfunc; + sortinfo.key = key; + oids = (Oid *) palloc(nparts * sizeof(Oid)); i = 0; foreach(cell, partoids) @@ -453,7 +474,7 @@ RelationBuildPartitionDesc(Relation rel) } qsort_arg(all_values, ndatums, sizeof(PartitionListValue *), - qsort_partition_list_value_cmp, (void *) key); + qsort_partition_list_value_cmp, (void *) &sortinfo); } else if (key->strategy == PARTITION_STRATEGY_RANGE) { @@ -506,7 +527,7 @@ RelationBuildPartitionDesc(Relation rel) qsort_arg(all_bounds, ndatums, sizeof(PartitionRangeBound *), qsort_partition_rbound_cmp, - (void *) key); + (void *) &sortinfo); /* Save distinct bounds from all_bounds into rbounds. */ rbounds = (PartitionRangeBound **) @@ -538,7 +559,7 @@ RelationBuildPartitionDesc(Relation rel) if (cur->kind[j] != PARTITION_RANGE_DATUM_VALUE) break; - cmpval = FunctionCall2Coll(&key->partsupfunc[j], + cmpval = FunctionCall2Coll(&partsupfunc[j], key->partcollation[j], cur->datums[j], prev->datums[j]); @@ -844,6 +865,40 @@ RelationGetDefaultPartitionOid(Relation rel) } /* + * partition_getprocinfo + * Return fmgr lookup info of partition support procs from relcache + * + * If it's not been built yet by calling fmgr.c, do that and add it to + * relcache. + */ +FmgrInfo * +partition_getprocinfo(Relation rel, PartitionKey key, int partattoff) +{ + FmgrInfo *info; + + info = rel->rd_partsupfunc; + + Assert(info != NULL); + + info += partattoff; + + /* Initialize the lookup info if first time through */ + if (info->fn_oid == InvalidOid) + { + RegProcedure *func = key->partsupfuncid; + RegProcedure procId; + + Assert(func != NULL); + + procId = func[partattoff]; + Assert(RegProcedureIsValid(procId)); + fmgr_info_cxt(procId, info, rel->rd_partcxt); + } + + return info; +} + +/* * RelationGetPartitionQual * * Returns a list of partition quals @@ -900,8 +955,7 @@ static PartitionKey partition_key_copy(PartitionKey fromkey) { PartitionKey newkey; - int n, - i; + int n; Assert(fromkey != NULL); @@ -921,11 +975,8 @@ partition_key_copy(PartitionKey fromkey) newkey->partopcintype = (Oid *) palloc(n * sizeof(Oid)); memcpy(newkey->partopcintype, fromkey->partopcintype, n * sizeof(Oid)); - newkey->partsupfunc = (FmgrInfo *) palloc(n * sizeof(FmgrInfo)); - for (i = 0; i < fromkey->partnatts; i++) - fmgr_info_copy(&newkey->partsupfunc[i], - &fromkey->partsupfunc[i], - CurrentMemoryContext); + newkey->partsupfuncid = (Oid *) palloc(n * sizeof(Oid)); + memcpy(newkey->partsupfuncid, fromkey->partsupfuncid, n * sizeof(Oid)); newkey->partcollation = (Oid *) palloc(n * sizeof(Oid)); memcpy(newkey->partcollation, fromkey->partcollation, n * sizeof(Oid)); @@ -1059,9 +1110,10 @@ qsort_partition_list_value_cmp(const void *a, const void *b, void *arg) { Datum val1 = (*(const PartitionListValue **) a)->value, val2 = (*(const PartitionListValue **) b)->value; - PartitionKey key = (PartitionKey) arg; + PartitionBoundSortInfo *sortinfo = (PartitionBoundSortInfo *) arg; + PartitionKey key = sortinfo->key; - return DatumGetInt32(FunctionCall2Coll(&key->partsupfunc[0], + return DatumGetInt32(FunctionCall2Coll(&sortinfo->partsupfunc[0], key->partcollation[0], val1, val2)); } @@ -1072,9 +1124,10 @@ qsort_partition_rbound_cmp(const void *a, const void *b, void *arg) { PartitionRangeBound *b1 = (*(PartitionRangeBound *const *) a); PartitionRangeBound *b2 = (*(PartitionRangeBound *const *) b); - PartitionKey key = (PartitionKey) arg; + PartitionBoundSortInfo *sortinfo = (PartitionBoundSortInfo *) arg; + PartitionKey key = sortinfo->key; - return partition_rbound_cmp(key->partnatts, key->partsupfunc, + return partition_rbound_cmp(key->partnatts, sortinfo->partsupfunc, key->partcollation, b1->datums, b1->kind, b1->lower, b2); } diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 16081bc932..dbd41d365e 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -1157,6 +1157,7 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) { relation->rd_partcxt = NULL; relation->rd_partkey = NULL; + relation->rd_partsupfunc = NULL; relation->rd_partdesc = NULL; relation->rd_partcheck = NIL; } @@ -5509,6 +5510,7 @@ load_relcache_init_file(bool shared) rel->rd_rsdesc = NULL; rel->rd_partcxt = NULL; rel->rd_partkey = NULL; + rel->rd_partsupfunc = NULL; rel->rd_partdesc = NULL; rel->rd_partcheck = NIL; rel->rd_indexprs = NIL; diff --git a/src/include/executor/execPartition.h b/src/include/executor/execPartition.h index b5dc53bfcb..47eedb91bb 100644 --- a/src/include/executor/execPartition.h +++ b/src/include/executor/execPartition.h @@ -25,6 +25,7 @@ * reldesc Relation descriptor of the table * key Partition key information of the table * keystate Execution state required for expressions in the partition key + * partsupfunc fmgr lookup info of partition support functions * nparts Number of partitions of the table * boundinfo PartitionBoundInfo of the table * tupslot A standalone TupleTableSlot initialized with this table's tuple @@ -42,6 +43,7 @@ typedef struct PartitionDispatchData Relation reldesc; PartitionKey key; List *keystate; /* list of ExprState */ + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; int nparts; PartitionBoundInfo boundinfo; TupleTableSlot *tupslot; diff --git a/src/include/partitioning/partprune.h b/src/include/partitioning/partprune.h index 114a9594be..44f0ad3706 100644 --- a/src/include/partitioning/partprune.h +++ b/src/include/partitioning/partprune.h @@ -31,7 +31,7 @@ typedef struct PartitionPruneContext Oid *partopfamily; Oid *partopcintype; Oid *partcollation; - FmgrInfo *partsupfunc; + FmgrInfo partsupfunc[PARTITION_MAX_KEYS]; /* Number of partitions */ int nparts; diff --git a/src/include/utils/partcache.h b/src/include/utils/partcache.h index b037bb00d5..e9a133ec76 100644 --- a/src/include/utils/partcache.h +++ b/src/include/utils/partcache.h @@ -32,7 +32,7 @@ typedef struct PartitionKeyData Oid *partopfamily; /* OIDs of operator families */ Oid *partopcintype; /* OIDs of opclass declared input data types */ - FmgrInfo *partsupfunc; /* lookup info for support funcs */ + Oid *partsupfuncid; /* partition support func OIDs */ /* Partitioning collation per attribute */ Oid *partcollation; @@ -49,6 +49,8 @@ typedef struct PartitionKeyData extern void RelationBuildPartitionKey(Relation relation); extern void RelationBuildPartitionDesc(Relation rel); extern PartitionKey RelationGetPartitionKey(Relation relation); +extern FmgrInfo *partition_getprocinfo(Relation rel, PartitionKey key, + int partattoff); extern int RelationGetPartitionCount(Relation relation); extern Oid *RelationGetPartitionOids(Relation relation); extern PartitionBoundInfo RelationGetPartitionBounds(Relation relation); diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 378401abca..930e4363c1 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -98,6 +98,8 @@ typedef struct RelationData MemoryContext rd_partcxt; /* private memory cxt for the values contained * in the fields related to partitioning */ struct PartitionKeyData *rd_partkey; /* partition key, or NULL */ + FmgrInfo *rd_partsupfunc; /* fmgr lookup info of partition support + * functions */ struct PartitionDescData *rd_partdesc; /* partitions, or NULL */ List *rd_partcheck; /* partition CHECK quals */ -- 2.11.0