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

Commit 815ef2f

Browse files
committed
Don't constraint-exclude partitioned tables as much
We only need to invoke constraint exclusion on partitioned tables when they are a partition, and they themselves contain a default partition; it's not necessary otherwise, and it's expensive, so avoid it. Also, we were trying once for each clause separately, but we can do it for all the clauses at once. While at it, centralize setting of RelOptInfo->partition_qual instead of computing it in slightly different ways in different places. Per complaints from Simon Riggs about 4e85642; reviewed by Yuzuko Hosoya, Kyotaro Horiguchi. Author: Amit Langote. I (Álvaro) again mangled the patch somewhat. Discussion: https://postgr.es/m/CANP8+j+tMCY=nEcQeqQam85=uopLBtX-2vHiLD2bbp7iQQUKpA@mail.gmail.com
1 parent 416c75c commit 815ef2f

File tree

2 files changed

+65
-65
lines changed

2 files changed

+65
-65
lines changed

src/backend/optimizer/util/plancat.c

+39-20
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ static void set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel,
7878
static PartitionScheme find_partition_scheme(PlannerInfo *root, Relation rel);
7979
static void set_baserel_partition_key_exprs(Relation relation,
8080
RelOptInfo *rel);
81+
static void set_baserel_partition_constraint(Relation relation,
82+
RelOptInfo *rel);
83+
8184

8285
/*
8386
* get_relation_info -
@@ -1267,25 +1270,9 @@ get_relation_constraints(PlannerInfo *root,
12671270
*/
12681271
if (include_partition && relation->rd_rel->relispartition)
12691272
{
1270-
List *pcqual = RelationGetPartitionQual(relation);
1271-
1272-
if (pcqual)
1273-
{
1274-
/*
1275-
* Run the partition quals through const-simplification similar to
1276-
* check constraints. We skip canonicalize_qual, though, because
1277-
* partition quals should be in canonical form already; also,
1278-
* since the qual is in implicit-AND format, we'd have to
1279-
* explicitly convert it to explicit-AND format and back again.
1280-
*/
1281-
pcqual = (List *) eval_const_expressions(root, (Node *) pcqual);
1282-
1283-
/* Fix Vars to have the desired varno */
1284-
if (varno != 1)
1285-
ChangeVarNodes((Node *) pcqual, 1, varno, 0);
1286-
1287-
result = list_concat(result, pcqual);
1288-
}
1273+
/* make sure rel->partition_qual is set */
1274+
set_baserel_partition_constraint(relation, rel);
1275+
result = list_concat(result, rel->partition_qual);
12891276
}
12901277

12911278
table_close(relation, NoLock);
@@ -2149,7 +2136,7 @@ set_relation_partition_info(PlannerInfo *root, RelOptInfo *rel,
21492136
rel->boundinfo = partdesc->boundinfo;
21502137
rel->nparts = partdesc->nparts;
21512138
set_baserel_partition_key_exprs(relation, rel);
2152-
rel->partition_qual = RelationGetPartitionQual(relation);
2139+
set_baserel_partition_constraint(relation, rel);
21532140
}
21542141

21552142
/*
@@ -2324,3 +2311,35 @@ set_baserel_partition_key_exprs(Relation relation,
23242311
*/
23252312
rel->nullable_partexprs = (List **) palloc0(sizeof(List *) * partnatts);
23262313
}
2314+
2315+
/*
2316+
* set_baserel_partition_constraint
2317+
*
2318+
* Builds the partition constraint for the given base relation and sets it
2319+
* in the given RelOptInfo. All Var nodes are restamped with the relid of the
2320+
* given relation.
2321+
*/
2322+
static void
2323+
set_baserel_partition_constraint(Relation relation, RelOptInfo *rel)
2324+
{
2325+
List *partconstr;
2326+
2327+
if (rel->partition_qual) /* already done */
2328+
return;
2329+
2330+
/*
2331+
* Run the partition quals through const-simplification similar to check
2332+
* constraints. We skip canonicalize_qual, though, because partition
2333+
* quals should be in canonical form already; also, since the qual is in
2334+
* implicit-AND format, we'd have to explicitly convert it to explicit-AND
2335+
* format and back again.
2336+
*/
2337+
partconstr = RelationGetPartitionQual(relation);
2338+
if (partconstr)
2339+
{
2340+
partconstr = (List *) expression_planner((Expr *) partconstr);
2341+
if (rel->relid != 1)
2342+
ChangeVarNodes((Node *) partconstr, 1, rel->relid, 0);
2343+
rel->partition_qual = partconstr;
2344+
}
2345+
}

src/backend/partitioning/partprune.c

+26-45
Original file line numberDiff line numberDiff line change
@@ -619,31 +619,16 @@ gen_partprune_steps(RelOptInfo *rel, List *clauses, PartClauseTarget target,
619619
context->target = target;
620620

621621
/*
622-
* For sub-partitioned tables there's a corner case where if the
623-
* sub-partitioned table shares any partition keys with its parent, then
624-
* it's possible that the partitioning hierarchy allows the parent
625-
* partition to only contain a narrower range of values than the
626-
* sub-partitioned table does. In this case it is possible that we'd
627-
* include partitions that could not possibly have any tuples matching
628-
* 'clauses'. The possibility of such a partition arrangement is perhaps
629-
* unlikely for non-default partitions, but it may be more likely in the
630-
* case of default partitions, so we'll add the parent partition table's
631-
* partition qual to the clause list in this case only. This may result
632-
* in the default partition being eliminated.
622+
* If this partitioned table is in turn a partition, and it shares any
623+
* partition keys with its parent, then it's possible that the hierarchy
624+
* allows the parent a narrower range of values than some of its
625+
* partitions (particularly the default one). This is normally not
626+
* useful, but it can be to prune the default partition.
633627
*/
634-
if (partition_bound_has_default(rel->boundinfo) &&
635-
rel->partition_qual != NIL)
628+
if (partition_bound_has_default(rel->boundinfo) && rel->partition_qual)
636629
{
637-
List *partqual = rel->partition_qual;
638-
639-
partqual = (List *) expression_planner((Expr *) partqual);
640-
641-
/* Fix Vars to have the desired varno */
642-
if (rel->relid != 1)
643-
ChangeVarNodes((Node *) partqual, 1, rel->relid, 0);
644-
645630
/* Make a copy to avoid modifying the passed-in List */
646-
clauses = list_concat_copy(clauses, partqual);
631+
clauses = list_concat_copy(clauses, rel->partition_qual);
647632
}
648633

649634
/* Down into the rabbit-hole. */
@@ -867,6 +852,25 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context,
867852
List *result = NIL;
868853
ListCell *lc;
869854

855+
/*
856+
* If this partitioned relation has a default partition and is itself
857+
* a partition (as evidenced by partition_qual being not NIL), we first
858+
* check if the clauses contradict the partition constraint. If they do,
859+
* there's no need to generate any steps as it'd already be proven that no
860+
* partitions need to be scanned.
861+
*
862+
* This is a measure of last resort only to be used because the default
863+
* partition cannot be pruned using the steps generated from clauses that
864+
* contradict the parent's partition constraint; regular pruning, which is
865+
* cheaper, is sufficient when no default partition exists.
866+
*/
867+
if (partition_bound_has_default(context->rel->boundinfo) &&
868+
predicate_refuted_by(context->rel->partition_qual, clauses, false))
869+
{
870+
context->contradictory = true;
871+
return NIL;
872+
}
873+
870874
memset(keyclauses, 0, sizeof(keyclauses));
871875
foreach(lc, clauses)
872876
{
@@ -1019,29 +1023,6 @@ gen_partprune_steps_internal(GeneratePruningStepsContext *context,
10191023
*/
10201024
}
10211025

1022-
/*
1023-
* If the clause contradicts the partition constraint, mark the clause
1024-
* as contradictory and we're done. This is particularly helpful to
1025-
* prune the default partition.
1026-
*/
1027-
if (context->rel->partition_qual)
1028-
{
1029-
List *partconstr;
1030-
1031-
partconstr = (List *)
1032-
expression_planner((Expr *) context->rel->partition_qual);
1033-
if (context->rel->relid != 1)
1034-
ChangeVarNodes((Node *) partconstr, 1,
1035-
context->rel->relid, 0);
1036-
if (predicate_refuted_by(partconstr,
1037-
list_make1(clause),
1038-
false))
1039-
{
1040-
context->contradictory = true;
1041-
return NIL;
1042-
}
1043-
}
1044-
10451026
/*
10461027
* See if we can match this clause to any of the partition keys.
10471028
*/

0 commit comments

Comments
 (0)