Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7ee5f88

Browse files
committed
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.
1 parent 16fbac3 commit 7ee5f88

File tree

3 files changed

+53
-58
lines changed

3 files changed

+53
-58
lines changed

src/backend/partitioning/partbounds.c

+28-38
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,12 @@ static int32 qsort_partition_list_value_cmp(const void *a, const void *b,
7070
void *arg);
7171
static int32 qsort_partition_rbound_cmp(const void *a, const void *b,
7272
void *arg);
73-
static PartitionBoundInfo create_hash_bounds(List *boundspecs,
74-
PartitionKey key,
75-
int **mapping);
76-
static PartitionBoundInfo create_list_bounds(List *boundspecs,
77-
PartitionKey key,
78-
int **mapping);
79-
static PartitionBoundInfo create_range_bounds(List *boundspecs,
80-
PartitionKey key,
81-
int **mapping);
73+
static PartitionBoundInfo create_hash_bounds(PartitionBoundSpec **boundspecs,
74+
int nparts, PartitionKey key, int **mapping);
75+
static PartitionBoundInfo create_list_bounds(PartitionBoundSpec **boundspecs,
76+
int nparts, PartitionKey key, int **mapping);
77+
static PartitionBoundInfo create_range_bounds(PartitionBoundSpec **boundspecs,
78+
int nparts, PartitionKey key, int **mapping);
8279
static PartitionRangeBound *make_one_partition_rbound(PartitionKey key, int index,
8380
List *datums, bool lower);
8481
static int32 partition_hbound_cmp(int modulus1, int remainder1, int modulus2,
@@ -169,9 +166,9 @@ get_qual_from_partbound(Relation rel, Relation parent,
169166
* current memory context.
170167
*/
171168
PartitionBoundInfo
172-
partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping)
169+
partition_bounds_create(PartitionBoundSpec **boundspecs, int nparts,
170+
PartitionKey key, int **mapping)
173171
{
174-
int nparts = list_length(boundspecs);
175172
int i;
176173

177174
Assert(nparts > 0);
@@ -199,13 +196,13 @@ partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping)
199196
switch (key->strategy)
200197
{
201198
case PARTITION_STRATEGY_HASH:
202-
return create_hash_bounds(boundspecs, key, mapping);
199+
return create_hash_bounds(boundspecs, nparts, key, mapping);
203200

204201
case PARTITION_STRATEGY_LIST:
205-
return create_list_bounds(boundspecs, key, mapping);
202+
return create_list_bounds(boundspecs, nparts, key, mapping);
206203

207204
case PARTITION_STRATEGY_RANGE:
208-
return create_range_bounds(boundspecs, key, mapping);
205+
return create_range_bounds(boundspecs, nparts, key, mapping);
209206

210207
default:
211208
elog(ERROR, "unexpected partition strategy: %d",
@@ -222,13 +219,12 @@ partition_bounds_create(List *boundspecs, PartitionKey key, int **mapping)
222219
* Create a PartitionBoundInfo for a hash partitioned table
223220
*/
224221
static PartitionBoundInfo
225-
create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping)
222+
create_hash_bounds(PartitionBoundSpec **boundspecs, int nparts,
223+
PartitionKey key, int **mapping)
226224
{
227225
PartitionBoundInfo boundinfo;
228226
PartitionHashBound **hbounds = NULL;
229-
ListCell *cell;
230-
int i,
231-
nparts = list_length(boundspecs);
227+
int i;
232228
int ndatums = 0;
233229
int greatest_modulus;
234230

@@ -244,10 +240,9 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping)
244240
palloc(nparts * sizeof(PartitionHashBound *));
245241

246242
/* Convert from node to the internal representation */
247-
i = 0;
248-
foreach(cell, boundspecs)
243+
for (i = 0; i < nparts; i++)
249244
{
250-
PartitionBoundSpec *spec = castNode(PartitionBoundSpec, lfirst(cell));
245+
PartitionBoundSpec *spec = boundspecs[i];
251246

252247
if (spec->strategy != PARTITION_STRATEGY_HASH)
253248
elog(ERROR, "invalid strategy in partition bound spec");
@@ -256,7 +251,6 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping)
256251
hbounds[i]->modulus = spec->modulus;
257252
hbounds[i]->remainder = spec->remainder;
258253
hbounds[i]->index = i;
259-
i++;
260254
}
261255

262256
/* Sort all the bounds in ascending order */
@@ -307,7 +301,8 @@ create_hash_bounds(List *boundspecs, PartitionKey key, int **mapping)
307301
* Create a PartitionBoundInfo for a list partitioned table
308302
*/
309303
static PartitionBoundInfo
310-
create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
304+
create_list_bounds(PartitionBoundSpec **boundspecs, int nparts,
305+
PartitionKey key, int **mapping)
311306
{
312307
PartitionBoundInfo boundinfo;
313308
PartitionListValue **all_values = NULL;
@@ -327,9 +322,9 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
327322
boundinfo->default_index = -1;
328323

329324
/* Create a unified list of non-null values across all partitions. */
330-
foreach(cell, boundspecs)
325+
for (i = 0; i < nparts; i++)
331326
{
332-
PartitionBoundSpec *spec = castNode(PartitionBoundSpec, lfirst(cell));
327+
PartitionBoundSpec *spec = boundspecs[i];
333328
ListCell *c;
334329

335330
if (spec->strategy != PARTITION_STRATEGY_LIST)
@@ -343,7 +338,6 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
343338
if (spec->is_default)
344339
{
345340
default_index = i;
346-
i++;
347341
continue;
348342
}
349343

@@ -374,8 +368,6 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
374368
if (list_value)
375369
non_null_values = lappend(non_null_values, list_value);
376370
}
377-
378-
i++;
379371
}
380372

381373
ndatums = list_length(non_null_values);
@@ -458,7 +450,7 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
458450
}
459451

460452
/* All partition must now have been assigned canonical indexes. */
461-
Assert(next_index == list_length(boundspecs));
453+
Assert(next_index == nparts);
462454
return boundinfo;
463455
}
464456

@@ -467,16 +459,15 @@ create_list_bounds(List *boundspecs, PartitionKey key, int **mapping)
467459
* Create a PartitionBoundInfo for a range partitioned table
468460
*/
469461
static PartitionBoundInfo
470-
create_range_bounds(List *boundspecs, PartitionKey key, int **mapping)
462+
create_range_bounds(PartitionBoundSpec **boundspecs, int nparts,
463+
PartitionKey key, int **mapping)
471464
{
472465
PartitionBoundInfo boundinfo;
473466
PartitionRangeBound **rbounds = NULL;
474467
PartitionRangeBound **all_bounds,
475468
*prev;
476-
ListCell *cell;
477469
int i,
478-
k,
479-
nparts = list_length(boundspecs);
470+
k;
480471
int ndatums = 0;
481472
int default_index = -1;
482473
int next_index = 0;
@@ -493,10 +484,10 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping)
493484
palloc0(2 * nparts * sizeof(PartitionRangeBound *));
494485

495486
/* Create a unified list of range bounds across all the partitions. */
496-
i = ndatums = 0;
497-
foreach(cell, boundspecs)
487+
ndatums = 0;
488+
for (i = 0; i < nparts; i++)
498489
{
499-
PartitionBoundSpec *spec = castNode(PartitionBoundSpec, lfirst(cell));
490+
PartitionBoundSpec *spec = boundspecs[i];
500491
PartitionRangeBound *lower,
501492
*upper;
502493

@@ -510,15 +501,14 @@ create_range_bounds(List *boundspecs, PartitionKey key, int **mapping)
510501
*/
511502
if (spec->is_default)
512503
{
513-
default_index = i++;
504+
default_index = i;
514505
continue;
515506
}
516507

517508
lower = make_one_partition_rbound(key, i, spec->lowerdatums, true);
518509
upper = make_one_partition_rbound(key, i, spec->upperdatums, false);
519510
all_bounds[ndatums++] = lower;
520511
all_bounds[ndatums++] = upper;
521-
i++;
522512
}
523513

524514
Assert(ndatums == nparts * 2 ||

src/backend/utils/cache/partcache.c

+23-17
Original file line numberDiff line numberDiff line change
@@ -255,28 +255,36 @@ void
255255
RelationBuildPartitionDesc(Relation rel)
256256
{
257257
PartitionDesc partdesc;
258-
PartitionBoundInfo boundinfo;
258+
PartitionBoundInfo boundinfo = NULL;
259259
List *inhoids;
260-
List *boundspecs = NIL;
260+
PartitionBoundSpec **boundspecs = NULL;
261+
Oid *oids = NULL;
261262
ListCell *cell;
262263
int i,
263264
nparts;
264265
PartitionKey key = RelationGetPartitionKey(rel);
265266
MemoryContext oldcxt;
266-
Oid *oids_orig;
267267
int *mapping;
268268

269269
/* Get partition oids from pg_inherits */
270270
inhoids = find_inheritance_children(RelationGetRelid(rel), NoLock);
271+
nparts = list_length(inhoids);
271272

272-
/* Collect bound spec nodes in a list */
273+
if (nparts > 0)
274+
{
275+
oids = palloc(nparts * sizeof(Oid));
276+
boundspecs = palloc(nparts * sizeof(PartitionBoundSpec *));
277+
}
278+
279+
/* Collect bound spec nodes for each partition */
280+
i = 0;
273281
foreach(cell, inhoids)
274282
{
275283
Oid inhrelid = lfirst_oid(cell);
276284
HeapTuple tuple;
277285
Datum datum;
278286
bool isnull;
279-
Node *boundspec;
287+
PartitionBoundSpec *boundspec;
280288

281289
tuple = SearchSysCache1(RELOID, inhrelid);
282290
if (!HeapTupleIsValid(tuple))
@@ -287,14 +295,16 @@ RelationBuildPartitionDesc(Relation rel)
287295
&isnull);
288296
if (isnull)
289297
elog(ERROR, "null relpartbound for relation %u", inhrelid);
290-
boundspec = (Node *) stringToNode(TextDatumGetCString(datum));
298+
boundspec = stringToNode(TextDatumGetCString(datum));
299+
if (!IsA(boundspec, PartitionBoundSpec))
300+
elog(ERROR, "invalid relpartbound for relation %u", inhrelid);
291301

292302
/*
293303
* Sanity check: If the PartitionBoundSpec says this is the default
294304
* partition, its OID should correspond to whatever's stored in
295305
* pg_partitioned_table.partdefid; if not, the catalog is corrupt.
296306
*/
297-
if (castNode(PartitionBoundSpec, boundspec)->is_default)
307+
if (boundspec->is_default)
298308
{
299309
Oid partdefid;
300310

@@ -304,12 +314,12 @@ RelationBuildPartitionDesc(Relation rel)
304314
inhrelid, partdefid);
305315
}
306316

307-
boundspecs = lappend(boundspecs, boundspec);
317+
oids[i] = inhrelid;
318+
boundspecs[i] = boundspec;
319+
++i;
308320
ReleaseSysCache(tuple);
309321
}
310322

311-
nparts = list_length(boundspecs);
312-
313323
/* Now build the actual relcache partition descriptor */
314324
rel->rd_pdcxt = AllocSetContextCreate(CacheMemoryContext,
315325
"partition descriptor",
@@ -330,11 +340,7 @@ RelationBuildPartitionDesc(Relation rel)
330340
}
331341

332342
/* First create PartitionBoundInfo */
333-
boundinfo = partition_bounds_create(boundspecs, key, &mapping);
334-
oids_orig = (Oid *) palloc(sizeof(Oid) * partdesc->nparts);
335-
i = 0;
336-
foreach(cell, inhoids)
337-
oids_orig[i++] = lfirst_oid(cell);
343+
boundinfo = partition_bounds_create(boundspecs, nparts, key, &mapping);
338344

339345
/* Now copy boundinfo and oids into partdesc. */
340346
oldcxt = MemoryContextSwitchTo(rel->rd_pdcxt);
@@ -352,10 +358,10 @@ RelationBuildPartitionDesc(Relation rel)
352358
{
353359
int index = mapping[i];
354360

355-
partdesc->oids[index] = oids_orig[i];
361+
partdesc->oids[index] = oids[i];
356362
/* Record if the partition is a leaf partition */
357363
partdesc->is_leaf[index] =
358-
(get_rel_relkind(oids_orig[i]) != RELKIND_PARTITIONED_TABLE);
364+
(get_rel_relkind(oids[i]) != RELKIND_PARTITIONED_TABLE);
359365
}
360366
MemoryContextSwitchTo(oldcxt);
361367

src/include/partitioning/partbounds.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,8 @@ extern uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc,
8080
Datum *values, bool *isnull);
8181
extern List *get_qual_from_partbound(Relation rel, Relation parent,
8282
PartitionBoundSpec *spec);
83-
extern PartitionBoundInfo partition_bounds_create(List *boundspecs,
84-
PartitionKey key,
85-
int **mapping);
83+
extern PartitionBoundInfo partition_bounds_create(PartitionBoundSpec **boundspecs,
84+
int nparts, PartitionKey key, int **mapping);
8685
extern bool partition_bounds_equal(int partnatts, int16 *parttyplen,
8786
bool *parttypbyval, PartitionBoundInfo b1,
8887
PartitionBoundInfo b2);

0 commit comments

Comments
 (0)