Commit 7ee5f88e authored by Robert Haas's avatar Robert Haas

Reduce unnecessary list construction in RelationBuildPartitionDesc.

The 'partoids' list which was constructed by the previous version
of this code was necessarily identical to 'inhoids'.  There's no
point to duplicating the list, so avoid that.  Instead, construct
the array representation directly from the original 'inhoids' list.

Also, use an array rather than a list for 'boundspecs'.  We know
exactly how many items we need to store, so there's really no
reason to use a list.  Using an array instead reduces the number
of memory allocations we perform.

Patch by me, reviewed by Michael Paquier and Amit Langote, the
latter of whom also helped with rebasing.
parent 16fbac39
...@@ -70,15 +70,12 @@ static int32 qsort_partition_list_value_cmp(const void *a, const void *b, ...@@ -70,15 +70,12 @@ static int32 qsort_partition_list_value_cmp(const void *a, const void *b,
void *arg); void *arg);
static int32 qsort_partition_rbound_cmp(const void *a, const void *b, static int32 qsort_partition_rbound_cmp(const void *a, const void *b,
void *arg); void *arg);
static PartitionBoundInfo create_hash_bounds(List *boundspecs, static PartitionBoundInfo create_hash_bounds(PartitionBoundSpec **boundspecs,
PartitionKey key, int nparts, PartitionKey key, int **mapping);
int **mapping); static PartitionBoundInfo create_list_bounds(PartitionBoundSpec **boundspecs,
static PartitionBoundInfo create_list_bounds(List *boundspecs, int nparts, PartitionKey key, int **mapping);
PartitionKey key, static PartitionBoundInfo create_range_bounds(PartitionBoundSpec **boundspecs,
int **mapping); int nparts, PartitionKey key, int **mapping);
static PartitionBoundInfo create_range_bounds(List *boundspecs,
PartitionKey key,
int **mapping);
static PartitionRangeBound *make_one_partition_rbound(PartitionKey key, int index, static PartitionRangeBound *make_one_partition_rbound(PartitionKey key, int index,
List *datums, bool lower); List *datums, bool lower);
static int32 partition_hbound_cmp(int modulus1, int remainder1, int modulus2, static int32 partition_hbound_cmp(int modulus1, int remainder1, int modulus2,
...@@ -169,9 +166,9 @@ get_qual_from_partbound(Relation rel, Relation parent, ...@@ -169,9 +166,9 @@ get_qual_from_partbound(Relation rel, Relation parent,
* current memory context. * current memory context.
*/ */
PartitionBoundInfo PartitionBoundInfo
partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping) partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts,
PartitionKey key, int **mapping)
{ {
int nparts = list_length(boundspecs);
int i; int i;
Assert(nparts > 0); Assert(nparts > 0);
...@@ -199,13 +196,13 @@ partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping) ...@@ -199,13 +196,13 @@ partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping)
switch (key->strategy) switch (key->strategy)
{ {
case PARTITION_STRATEGY_HASH: case PARTITION_STRATEGY_HASH:
return create_hash_bounds(boundspecs, key, mapping); return create_hash_bounds(boundspecs, nparts, key, mapping);
case PARTITION_STRATEGY_LIST: case PARTITION_STRATEGY_LIST:
return create_list_bounds(boundspecs, key, mapping); return create_list_bounds(boundspecs, nparts, key, mapping);
case PARTITION_STRATEGY_RANGE: case PARTITION_STRATEGY_RANGE:
return create_range_bounds(boundspecs, key, mapping); return create_range_bounds(boundspecs, nparts, key, mapping);
default: default:
elog(ERROR, "unexpected partition strategy: %d", elog(ERROR, "unexpected partition strategy: %d",
...@@ -222,13 +219,12 @@ partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping) ...@@ -222,13 +219,12 @@ partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping)
* Create a PartitionBoundInfo for a hash partitioned table * Create a PartitionBoundInfo for a hash partitioned table
*/ */
static PartitionBoundInfo static PartitionBoundInfo
create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping) create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
PartitionKey key, int **mapping)
{ {
PartitionBoundInfo boundinfo; PartitionBoundInfo boundinfo;
PartitionHashBound **hbounds = NULL; PartitionHashBound **hbounds = NULL;
ListCell *cell; int i;
int i,
nparts = list_length(boundspecs);
int ndatums = 0; int ndatums = 0;
int greatest_modulus; int greatest_modulus;
...@@ -244,10 +240,9 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -244,10 +240,9 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping)
palloc(nparts * sizeof(PartitionHashBound *)); palloc(nparts * sizeof(PartitionHashBound *));
/* Convert from node to the internal representation */ /* Convert from node to the internal representation */
i = 0; for (i = 0; i < nparts; i++)
foreach(cell, boundspecs)
{ {
PartitionBoundSpec *spec = castNode(PartitionBoundSpec, lfirst(cell)); PartitionBoundSpec *spec = boundspecs[i];
if (spec->strategy != PARTITION_STRATEGY_HASH) if (spec->strategy != PARTITION_STRATEGY_HASH)
elog(ERROR, "invalid strategy in partition bound spec"); elog(ERROR, "invalid strategy in partition bound spec");
...@@ -256,7 +251,6 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -256,7 +251,6 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping)
hbounds[i]->modulus = spec->modulus; hbounds[i]->modulus = spec->modulus;
hbounds[i]->remainder = spec->remainder; hbounds[i]->remainder = spec->remainder;
hbounds[i]->index = i; hbounds[i]->index = i;
i++;
} }
/* Sort all the bounds in ascending order */ /* Sort all the bounds in ascending order */
...@@ -307,7 +301,8 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -307,7 +301,8 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping)
* Create a PartitionBoundInfo for a list partitioned table * Create a PartitionBoundInfo for a list partitioned table
*/ */
static PartitionBoundInfo static PartitionBoundInfo
create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
PartitionKey key, int **mapping)
{ {
PartitionBoundInfo boundinfo; PartitionBoundInfo boundinfo;
PartitionListValue **all_values = NULL; PartitionListValue **all_values = NULL;
...@@ -327,9 +322,9 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -327,9 +322,9 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
boundinfo->default_index = -1; boundinfo->default_index = -1;
/* Create a unified list of non-null values across all partitions. */ /* Create a unified list of non-null values across all partitions. */
foreach(cell, boundspecs) for (i = 0; i < nparts; i++)
{ {
PartitionBoundSpec *spec = castNode(PartitionBoundSpec, lfirst(cell)); PartitionBoundSpec *spec = boundspecs[i];
ListCell *c; ListCell *c;
if (spec->strategy != PARTITION_STRATEGY_LIST) if (spec->strategy != PARTITION_STRATEGY_LIST)
...@@ -343,7 +338,6 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -343,7 +338,6 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
if (spec->is_default) if (spec->is_default)
{ {
default_index = i; default_index = i;
i++;
continue; continue;
} }
...@@ -374,8 +368,6 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -374,8 +368,6 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
if (list_value) if (list_value)
non_null_values = lappend(non_null_values, list_value); non_null_values = lappend(non_null_values, list_value);
} }
i++;
} }
ndatums = list_length(non_null_values); ndatums = list_length(non_null_values);
...@@ -458,7 +450,7 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -458,7 +450,7 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
} }
/* All partition must now have been assigned canonical indexes. */ /* All partition must now have been assigned canonical indexes. */
Assert(next_index == list_length(boundspecs)); Assert(next_index == nparts);
return boundinfo; return boundinfo;
} }
...@@ -467,16 +459,15 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -467,16 +459,15 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
* Create a PartitionBoundInfo for a range partitioned table * Create a PartitionBoundInfo for a range partitioned table
*/ */
static PartitionBoundInfo static PartitionBoundInfo
create_range_bounds(List *boundspecs, PartitionKey key, int **mapping) create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
PartitionKey key, int **mapping)
{ {
PartitionBoundInfo boundinfo; PartitionBoundInfo boundinfo;
PartitionRangeBound **rbounds = NULL; PartitionRangeBound **rbounds = NULL;
PartitionRangeBound **all_bounds, PartitionRangeBound **all_bounds,
*prev; *prev;
ListCell *cell;
int i, int i,
k, k;
nparts = list_length(boundspecs);
int ndatums = 0; int ndatums = 0;
int default_index = -1; int default_index = -1;
int next_index = 0; int next_index = 0;
...@@ -493,10 +484,10 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -493,10 +484,10 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping)
palloc0(2 * nparts * sizeof(PartitionRangeBound *)); palloc0(2 * nparts * sizeof(PartitionRangeBound *));
/* Create a unified list of range bounds across all the partitions. */ /* Create a unified list of range bounds across all the partitions. */
i = ndatums = 0; ndatums = 0;
foreach(cell, boundspecs) for (i = 0; i < nparts; i++)
{ {
PartitionBoundSpec *spec = castNode(PartitionBoundSpec, lfirst(cell)); PartitionBoundSpec *spec = boundspecs[i];
PartitionRangeBound *lower, PartitionRangeBound *lower,
*upper; *upper;
...@@ -510,7 +501,7 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -510,7 +501,7 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping)
*/ */
if (spec->is_default) if (spec->is_default)
{ {
default_index = i++; default_index = i;
continue; continue;
} }
...@@ -518,7 +509,6 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping) ...@@ -518,7 +509,6 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping)
upper = make_one_partition_rbound(key, i, spec->upperdatums, false); upper = make_one_partition_rbound(key, i, spec->upperdatums, false);
all_bounds[ndatums++] = lower; all_bounds[ndatums++] = lower;
all_bounds[ndatums++] = upper; all_bounds[ndatums++] = upper;
i++;
} }
Assert(ndatums == nparts * 2 || Assert(ndatums == nparts * 2 ||
......
...@@ -255,28 +255,36 @@ void ...@@ -255,28 +255,36 @@ void
RelationBuildPartitionDesc(Relation rel) RelationBuildPartitionDesc(Relation rel)
{ {
PartitionDesc partdesc; PartitionDesc partdesc;
PartitionBoundInfo boundinfo; PartitionBoundInfo boundinfo = NULL;
List *inhoids; List *inhoids;
List *boundspecs = NIL; PartitionBoundSpec **boundspecs = NULL;
Oid *oids = NULL;
ListCell *cell; ListCell *cell;
int i, int i,
nparts; nparts;
PartitionKey key = RelationGetPartitionKey(rel); PartitionKey key = RelationGetPartitionKey(rel);
MemoryContext oldcxt; MemoryContext oldcxt;
Oid *oids_orig;
int *mapping; int *mapping;
/* Get partition oids from pg_inherits */ /* Get partition oids from pg_inherits */
inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock); inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock);
nparts = list_length(inhoids);
/* Collect bound spec nodes in a list */ if (nparts > 0)
{
oids = palloc(nparts * sizeof(Oid));
boundspecs = palloc(nparts * sizeof(PartitionBoundSpec *));
}
/* Collect bound spec nodes for each partition */
i = 0;
foreach(cell, inhoids) foreach(cell, inhoids)
{ {
Oid inhrelid = lfirst_oid(cell); Oid inhrelid = lfirst_oid(cell);
HeapTuple tuple; HeapTuple tuple;
Datum datum; Datum datum;
bool isnull; bool isnull;
Node *boundspec; PartitionBoundSpec *boundspec;
tuple = SearchSysCache1(RELOID, inhrelid); tuple = SearchSysCache1(RELOID, inhrelid);
if (!HeapTupleIsValid(tuple)) if (!HeapTupleIsValid(tuple))
...@@ -287,14 +295,16 @@ RelationBuildPartitionDesc(Relation rel) ...@@ -287,14 +295,16 @@ RelationBuildPartitionDesc(Relation rel)
&isnull); &isnull);
if (isnull) if (isnull)
elog(ERROR, "null relpartbound for relation %u", inhrelid); elog(ERROR, "null relpartbound for relation %u", inhrelid);
boundspec = (Node *) stringToNode(TextDatumGetCString(datum)); boundspec = stringToNode(TextDatumGetCString(datum));
if (!IsA(boundspec, PartitionBoundSpec))
elog(ERROR, "invalid relpartbound for relation %u", inhrelid);
/* /*
* Sanity check: If the PartitionBoundSpec says this is the default * Sanity check: If the PartitionBoundSpec says this is the default
* partition, its OID should correspond to whatever's stored in * partition, its OID should correspond to whatever's stored in
* pg_partitioned_table.partdefid; if not, the catalog is corrupt. * pg_partitioned_table.partdefid; if not, the catalog is corrupt.
*/ */
if (castNode(PartitionBoundSpec, boundspec)->is_default) if (boundspec->is_default)
{ {
Oid partdefid; Oid partdefid;
...@@ -304,12 +314,12 @@ RelationBuildPartitionDesc(Relation rel) ...@@ -304,12 +314,12 @@ RelationBuildPartitionDesc(Relation rel)
inhrelid, partdefid); inhrelid, partdefid);
} }
boundspecs = lappend(boundspecs, boundspec); oids[i] = inhrelid;
boundspecs[i] = boundspec;
++i;
ReleaseSysCache(tuple); ReleaseSysCache(tuple);
} }
nparts = list_length(boundspecs);
/* Now build the actual relcache partition descriptor */ /* Now build the actual relcache partition descriptor */
rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext, rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
"partition descriptor", "partition descriptor",
...@@ -330,11 +340,7 @@ RelationBuildPartitionDesc(Relation rel) ...@@ -330,11 +340,7 @@ RelationBuildPartitionDesc(Relation rel)
} }
/* First create PartitionBoundInfo */ /* First create PartitionBoundInfo */
boundinfo = partition_bounds_create(boundspecs, key, &mapping); boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
oids_orig = (Oid *) palloc(sizeof(Oid) * partdesc->nparts);
i = 0;
foreach(cell, inhoids)
oids_orig[i++] = lfirst_oid(cell);
/* Now copy boundinfo and oids into partdesc. */ /* Now copy boundinfo and oids into partdesc. */
oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt); oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
...@@ -352,10 +358,10 @@ RelationBuildPartitionDesc(Relation rel) ...@@ -352,10 +358,10 @@ RelationBuildPartitionDesc(Relation rel)
{ {
int index = mapping[i]; int index = mapping[i];
partdesc->oids[index] = oids_orig[i]; partdesc->oids[index] = oids[i];
/* Record if the partition is a leaf partition */ /* Record if the partition is a leaf partition */
partdesc->is_leaf[index] = partdesc->is_leaf[index] =
(get_rel_relkind(oids_orig[i]) != RELKIND_PARTITIONED_TABLE); (get_rel_relkind(oids[i]) != RELKIND_PARTITIONED_TABLE);
} }
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
......
...@@ -80,9 +80,8 @@ extern uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, ...@@ -80,9 +80,8 @@ extern uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc,
Datum *values, bool *isnull); Datum *values, bool *isnull);
extern List *get_qual_from_partbound(Relation rel, Relation parent, extern List *get_qual_from_partbound(Relation rel, Relation parent,
PartitionBoundSpec *spec); PartitionBoundSpec *spec);
extern PartitionBoundInfo partition_bounds_create(List *boundspecs, extern PartitionBoundInfo partition_bounds_create(PartitionBoundSpec **boundspecs,
PartitionKey key, int nparts, PartitionKey key, int **mapping);
int **mapping);
extern bool partition_bounds_equal(int partnatts, int16 *parttyplen, extern bool partition_bounds_equal(int partnatts, int16 *parttyplen,
bool *parttypbyval, PartitionBoundInfo b1, bool *parttypbyval, PartitionBoundInfo b1,
PartitionBoundInfo b2); PartitionBoundInfo b2);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment