Reduce unnecessary list construction in RelationBuildPartitionDesc.
authorRobert Haas <rhaas@postgresql.org>
Mon, 19 Nov 2018 17:10:41 +0000 (12:10 -0500)
committerRobert Haas <rhaas@postgresql.org>
Mon, 19 Nov 2018 17:10:41 +0000 (12:10 -0500)
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.

src/backend/partitioning/partbounds.c
src/backend/utils/cache/partcache.c
src/include/partitioning/partbounds.h

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