From 2fadf7c9cb35f3993e2d9cf91f8cd580fe5f59fb Mon Sep 17 00:00:00 2001 From: amit Date: Wed, 20 Mar 2019 13:27:37 +0900 Subject: [PATCH v2] Fix planner to load partition constraint in some cases For select queries that access a partition directly, we should load the partition constraint so that constraint exclusion can use it to exclude the partition based on query quals. When partitions are accessed indirectly via the parent table, it's unnecessary to load the partition constraint, because partition pruning will only select those partitions whose partition constraint satisfies query quals, making it unnecessary to run constraint exclusion on partitions. --- src/backend/optimizer/util/plancat.c | 10 +++++-- src/test/regress/expected/partition_prune.out | 41 +++++++++++++++++++++++++++ src/test/regress/sql/partition_prune.sql | 18 ++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 30f4dc151b..ce38a50afb 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -1270,10 +1270,14 @@ get_relation_constraints(PlannerInfo *root, * Append partition predicates, if any. * * For selects, partition pruning uses the parent table's partition bound - * descriptor, instead of constraint exclusion which is driven by the - * individual partition's partition constraint. + * descriptor, so there's no need to include the partition constraint for + * this case. However, if the partition is referenced directly in the + * query then no partition pruning will occur, so we'll include it in that + * case. */ - if (enable_partition_pruning && root->parse->commandType != CMD_SELECT) + if ((root->parse->commandType != CMD_SELECT && enable_partition_pruning) || + (root->parse->commandType == CMD_SELECT && + rel->reloptkind == RELOPT_BASEREL)) { List *pcqual = RelationGetPartitionQual(relation); diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out index 30946f77b6..dd2a3e27db 100644 --- a/src/test/regress/expected/partition_prune.out +++ b/src/test/regress/expected/partition_prune.out @@ -3637,4 +3637,45 @@ select * from listp where a = (select 2) and b <> 10; Filter: ((b <> 10) AND (a = $0)) (5 rows) +-- +-- check that a partition directly accessed in a query is excluded with +-- constraint_exclusion = on +-- +-- turn off partition pruning, so that it doesn't interfere +set enable_partition_pruning to off; +-- constraint exclusion doesn't apply +set constraint_exclusion to 'partition'; +explain (costs off) select * from listp1 where a = 2; + QUERY PLAN +-------------------- + Seq Scan on listp1 + Filter: (a = 2) +(2 rows) + +explain (costs off) select * from listp2 where a = 1; + QUERY PLAN +----------------------------- + Append + -> Seq Scan on listp2_10 + Filter: (a = 1) +(3 rows) + +-- constraint exclusion applies +set constraint_exclusion to 'on'; +explain (costs off) select * from listp1 where a = 2; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +explain (costs off) select * from listp2 where a = 1; + QUERY PLAN +-------------------------- + Result + One-Time Filter: false +(2 rows) + +reset constraint_exclusion; +reset enable_partition_pruning; drop table listp; diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql index dc327caffd..6650188918 100644 --- a/src/test/regress/sql/partition_prune.sql +++ b/src/test/regress/sql/partition_prune.sql @@ -985,4 +985,22 @@ create table listp2_10 partition of listp2 for values in (10); explain (analyze, costs off, summary off, timing off) select * from listp where a = (select 2) and b <> 10; +-- +-- check that a partition directly accessed in a query is excluded with +-- constraint_exclusion = on +-- + +-- turn off partition pruning, so that it doesn't interfere +set enable_partition_pruning to off; + +-- constraint exclusion doesn't apply +set constraint_exclusion to 'partition'; +explain (costs off) select * from listp1 where a = 2; +explain (costs off) select * from listp2 where a = 1; +-- constraint exclusion applies +set constraint_exclusion to 'on'; +explain (costs off) select * from listp1 where a = 2; +explain (costs off) select * from listp2 where a = 1; +reset constraint_exclusion; +reset enable_partition_pruning; drop table listp; -- 2.11.0