Commit 055fb8d3 authored by Alvaro Herrera's avatar Alvaro Herrera

Add GUC enable_partition_pruning

This controls both plan-time and execution-time new-style partition
pruning.  While finer-grain control is possible (maybe using an enum GUC
instead of boolean), there doesn't seem to be much need for that.

This new parameter controls partition pruning for all queries:
trivially, SELECT queries that affect partitioned tables are naturally
under its control since they are using the new technology.  However,
while UPDATE/DELETE queries do not use the new code, we make the new GUC
control their behavior also (stealing control from
constraint_exclusion), because it is more natural, and it leads to a
more natural transition to the future in which those queries will also
use the new pruning code.

Constraint exclusion still controls pruning for regular inheritance
situations (those not involving partitioned tables).

Author: David Rowley
Review: Amit Langote, Ashutosh Bapat, Justin Pryzby, David G. Johnston
Discussion: https://postgr.es/m/CAKJS1f_0HwsxJG9m+nzU+CizxSdGtfe6iF_ykPYBiYft302DCw@mail.gmail.com
parent 4df58f7e
...@@ -3826,6 +3826,23 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class=" ...@@ -3826,6 +3826,23 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry id="guc-enable-partition-pruning" xreflabel="enable_partition_pruning">
<term><varname>enable_partition_pruning</varname> (<type>boolean</type>)
<indexterm>
<primary><varname>enable_partition_pruning</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Enables or disables the query planner's ability to eliminate a
partitioned table's partitions from query plans. This also controls
the planner's ability to generate query plans which allow the query
executor to remove (ignore) partitions during query execution. The
default is <literal>on</literal>.
</para>
</listitem>
</varlistentry>
<varlistentry id="guc-enable-partitionwise-join" xreflabel="enable_partitionwise_join"> <varlistentry id="guc-enable-partitionwise-join" xreflabel="enable_partitionwise_join">
<term><varname>enable_partitionwise_join</varname> (<type>boolean</type>) <term><varname>enable_partitionwise_join</varname> (<type>boolean</type>)
<indexterm> <indexterm>
...@@ -4417,8 +4434,7 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class=" ...@@ -4417,8 +4434,7 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
<literal>partition</literal> (examine constraints only for inheritance child <literal>partition</literal> (examine constraints only for inheritance child
tables and <literal>UNION ALL</literal> subqueries). tables and <literal>UNION ALL</literal> subqueries).
<literal>partition</literal> is the default setting. <literal>partition</literal> is the default setting.
It is often used with inheritance and partitioned tables to It is often used with inheritance tables to improve performance.
improve performance.
</para> </para>
<para> <para>
...@@ -4441,11 +4457,11 @@ SELECT * FROM parent WHERE key = 2400; ...@@ -4441,11 +4457,11 @@ SELECT * FROM parent WHERE key = 2400;
<para> <para>
Currently, constraint exclusion is enabled by default Currently, constraint exclusion is enabled by default
only for cases that are often used to implement table partitioning. only for cases that are often used to implement table partitioning via
Turning it on for all tables imposes extra planning overhead that is inheritance tables. Turning it on for all tables imposes extra
quite noticeable on simple queries, and most often will yield no planning overhead that is quite noticeable on simple queries, and most
benefit for simple queries. If you have no partitioned tables often will yield no benefit for simple queries. If you have no
you might prefer to turn it off entirely. inheritance partitioned tables you might prefer to turn it off entirely.
</para> </para>
<para> <para>
......
...@@ -3196,7 +3196,7 @@ CREATE INDEX ON measurement (logdate); ...@@ -3196,7 +3196,7 @@ CREATE INDEX ON measurement (logdate);
<listitem> <listitem>
<para> <para>
Ensure that the <xref linkend="guc-constraint-exclusion"/> Ensure that the <xref linkend="guc-enable-partition-pruning"/>
configuration parameter is not disabled in <filename>postgresql.conf</filename>. configuration parameter is not disabled in <filename>postgresql.conf</filename>.
If it is, queries will not be optimized as desired. If it is, queries will not be optimized as desired.
</para> </para>
......
...@@ -2291,7 +2291,7 @@ _outPlannerInfo(StringInfo str, const PlannerInfo *node) ...@@ -2291,7 +2291,7 @@ _outPlannerInfo(StringInfo str, const PlannerInfo *node)
WRITE_FLOAT_FIELD(tuple_fraction, "%.4f"); WRITE_FLOAT_FIELD(tuple_fraction, "%.4f");
WRITE_FLOAT_FIELD(limit_tuples, "%.0f"); WRITE_FLOAT_FIELD(limit_tuples, "%.0f");
WRITE_UINT_FIELD(qual_security_level); WRITE_UINT_FIELD(qual_security_level);
WRITE_BOOL_FIELD(hasInheritedTarget); WRITE_ENUM_FIELD(inhTargetKind, InheritanceKind);
WRITE_BOOL_FIELD(hasJoinRTEs); WRITE_BOOL_FIELD(hasJoinRTEs);
WRITE_BOOL_FIELD(hasLateralRTEs); WRITE_BOOL_FIELD(hasLateralRTEs);
WRITE_BOOL_FIELD(hasDeletedRTEs); WRITE_BOOL_FIELD(hasDeletedRTEs);
......
...@@ -901,7 +901,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, ...@@ -901,7 +901,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
* store the relids of all partitions which could possibly contain a * store the relids of all partitions which could possibly contain a
* matching tuple, and skip anything else in the loop below. * matching tuple, and skip anything else in the loop below.
*/ */
if (rte->relkind == RELKIND_PARTITIONED_TABLE && if (enable_partition_pruning &&
rte->relkind == RELKIND_PARTITIONED_TABLE &&
rel->baserestrictinfo != NIL) rel->baserestrictinfo != NIL)
{ {
live_children = prune_append_rel_partitions(rel); live_children = prune_append_rel_partitions(rel);
......
...@@ -138,6 +138,7 @@ bool enable_partitionwise_join = false; ...@@ -138,6 +138,7 @@ bool enable_partitionwise_join = false;
bool enable_partitionwise_aggregate = false; bool enable_partitionwise_aggregate = false;
bool enable_parallel_append = true; bool enable_parallel_append = true;
bool enable_parallel_hash = true; bool enable_parallel_hash = true;
bool enable_partition_pruning = true;
typedef struct typedef struct
{ {
......
...@@ -1077,7 +1077,8 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path) ...@@ -1077,7 +1077,8 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path)
subplans = lappend(subplans, subplan); subplans = lappend(subplans, subplan);
} }
if (rel->reloptkind == RELOPT_BASEREL && if (enable_partition_pruning &&
rel->reloptkind == RELOPT_BASEREL &&
best_path->partitioned_rels != NIL) best_path->partitioned_rels != NIL)
{ {
List *prunequal; List *prunequal;
...@@ -1979,7 +1980,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path) ...@@ -1979,7 +1980,7 @@ create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
* create_modifytable_plan). Fortunately we can't be because there would * create_modifytable_plan). Fortunately we can't be because there would
* never be grouping in an UPDATE/DELETE; but let's Assert that. * never be grouping in an UPDATE/DELETE; but let's Assert that.
*/ */
Assert(!root->hasInheritedTarget); Assert(root->inhTargetKind == INHKIND_NONE);
Assert(root->grouping_map == NULL); Assert(root->grouping_map == NULL);
root->grouping_map = grouping_map; root->grouping_map = grouping_map;
...@@ -2141,7 +2142,7 @@ create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path) ...@@ -2141,7 +2142,7 @@ create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
* create_modifytable_plan). Fortunately we can't be because there would * create_modifytable_plan). Fortunately we can't be because there would
* never be aggregates in an UPDATE/DELETE; but let's Assert that. * never be aggregates in an UPDATE/DELETE; but let's Assert that.
*/ */
Assert(!root->hasInheritedTarget); Assert(root->inhTargetKind == INHKIND_NONE);
Assert(root->minmax_aggs == NIL); Assert(root->minmax_aggs == NIL);
root->minmax_aggs = best_path->mmaggregates; root->minmax_aggs = best_path->mmaggregates;
......
...@@ -623,7 +623,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, ...@@ -623,7 +623,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
root->grouping_map = NULL; root->grouping_map = NULL;
root->minmax_aggs = NIL; root->minmax_aggs = NIL;
root->qual_security_level = 0; root->qual_security_level = 0;
root->hasInheritedTarget = false; root->inhTargetKind = INHKIND_NONE;
root->hasRecursion = hasRecursion; root->hasRecursion = hasRecursion;
if (hasRecursion) if (hasRecursion)
root->wt_param_id = SS_assign_special_param(root); root->wt_param_id = SS_assign_special_param(root);
...@@ -1424,8 +1424,13 @@ inheritance_planner(PlannerInfo *root) ...@@ -1424,8 +1424,13 @@ inheritance_planner(PlannerInfo *root)
Assert(subroot->join_info_list == NIL); Assert(subroot->join_info_list == NIL);
/* and we haven't created PlaceHolderInfos, either */ /* and we haven't created PlaceHolderInfos, either */
Assert(subroot->placeholder_list == NIL); Assert(subroot->placeholder_list == NIL);
/* hack to mark target relation as an inheritance partition */
subroot->hasInheritedTarget = true; /*
* Mark if we're planning a query to a partitioned table or an
* inheritance parent.
*/
subroot->inhTargetKind =
partitioned_relids ? INHKIND_PARTITIONED : INHKIND_INHERITED;
/* /*
* If the child is further partitioned, remember it as a parent. Since * If the child is further partitioned, remember it as a parent. Since
......
...@@ -914,7 +914,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte, ...@@ -914,7 +914,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
subroot->grouping_map = NULL; subroot->grouping_map = NULL;
subroot->minmax_aggs = NIL; subroot->minmax_aggs = NIL;
subroot->qual_security_level = 0; subroot->qual_security_level = 0;
subroot->hasInheritedTarget = false; subroot->inhTargetKind = INHKIND_NONE;
subroot->hasRecursion = false; subroot->hasRecursion = false;
subroot->wt_param_id = -1; subroot->wt_param_id = -1;
subroot->non_recursive_path = NULL; subroot->non_recursive_path = NULL;
......
...@@ -1272,7 +1272,7 @@ get_relation_constraints(PlannerInfo *root, ...@@ -1272,7 +1272,7 @@ get_relation_constraints(PlannerInfo *root,
* descriptor, instead of constraint exclusion which is driven by the * descriptor, instead of constraint exclusion which is driven by the
* individual partition's partition constraint. * individual partition's partition constraint.
*/ */
if (root->parse->commandType != CMD_SELECT) if (enable_partition_pruning && root->parse->commandType != CMD_SELECT)
{ {
List *pcqual = RelationGetPartitionQual(relation); List *pcqual = RelationGetPartitionQual(relation);
...@@ -1415,14 +1415,41 @@ relation_excluded_by_constraints(PlannerInfo *root, ...@@ -1415,14 +1415,41 @@ relation_excluded_by_constraints(PlannerInfo *root,
return true; return true;
} }
/* Skip further tests if constraint exclusion is disabled for the rel */ /*
if (constraint_exclusion == CONSTRAINT_EXCLUSION_OFF || * Skip further tests, depending on constraint_exclusion.
(constraint_exclusion == CONSTRAINT_EXCLUSION_PARTITION && */
!(rel->reloptkind == RELOPT_OTHER_MEMBER_REL || switch (constraint_exclusion)
(root->hasInheritedTarget && {
rel->reloptkind == RELOPT_BASEREL && case CONSTRAINT_EXCLUSION_OFF:
rel->relid == root->parse->resultRelation)))) /*
return false; * Don't prune if feature turned off -- except if the relation is
* a partition. While partprune.c-style partition pruning is not
* yet in use for all cases (update/delete is not handled), it
* would be a UI horror to use different user-visible controls
* depending on such a volatile implementation detail. Therefore,
* for partitioned tables we use enable_partition_pruning to
* control this behavior.
*/
if (root->inhTargetKind == INHKIND_PARTITIONED)
break;
return false;
case CONSTRAINT_EXCLUSION_PARTITION:
/*
* When constraint_exclusion is set to 'partition' we only handle
* OTHER_MEMBER_RELs, or BASERELs in cases where the result target
* is an inheritance parent or a partitioned table.
*/
if ((rel->reloptkind != RELOPT_OTHER_MEMBER_REL) &&
!(rel->reloptkind == RELOPT_BASEREL &&
root->inhTargetKind != INHKIND_NONE &&
rel->relid == root->parse->resultRelation))
return false;
break;
case CONSTRAINT_EXCLUSION_ON:
break; /* always try to exclude */
}
/* /*
* Check for self-contradictory restriction clauses. We dare not make * Check for self-contradictory restriction clauses. We dare not make
......
...@@ -951,6 +951,17 @@ static struct config_bool ConfigureNamesBool[] = ...@@ -951,6 +951,17 @@ static struct config_bool ConfigureNamesBool[] =
true, true,
NULL, NULL, NULL NULL, NULL, NULL
}, },
{
{"enable_partition_pruning", PGC_USERSET, QUERY_TUNING_METHOD,
gettext_noop("Enable plan-time and run-time partition pruning."),
gettext_noop("Allows the query planner and executor to compare partition "
"bounds to conditions in the query to determine which "
"partitions must be scanned.")
},
&enable_partition_pruning,
true,
NULL, NULL, NULL
},
{ {
{"geqo", PGC_USERSET, QUERY_TUNING_GEQO, {"geqo", PGC_USERSET, QUERY_TUNING_GEQO,
gettext_noop("Enables genetic query optimization."), gettext_noop("Enables genetic query optimization."),
......
...@@ -308,6 +308,7 @@ ...@@ -308,6 +308,7 @@
#enable_partitionwise_join = off #enable_partitionwise_join = off
#enable_partitionwise_aggregate = off #enable_partitionwise_aggregate = off
#enable_parallel_hash = on #enable_parallel_hash = on
#enable_partition_pruning = on
# - Planner Cost Constants - # - Planner Cost Constants -
......
...@@ -82,6 +82,17 @@ typedef enum UpperRelationKind ...@@ -82,6 +82,17 @@ typedef enum UpperRelationKind
/* NB: UPPERREL_FINAL must be last enum entry; it's used to size arrays */ /* NB: UPPERREL_FINAL must be last enum entry; it's used to size arrays */
} UpperRelationKind; } UpperRelationKind;
/*
* This enum identifies which type of relation is being planned through the
* inheritance planner. INHKIND_NONE indicates the inheritance planner
* was not used.
*/
typedef enum InheritanceKind
{
INHKIND_NONE,
INHKIND_INHERITED,
INHKIND_PARTITIONED
} InheritanceKind;
/*---------- /*----------
* PlannerGlobal * PlannerGlobal
...@@ -298,8 +309,9 @@ typedef struct PlannerInfo ...@@ -298,8 +309,9 @@ typedef struct PlannerInfo
Index qual_security_level; /* minimum security_level for quals */ Index qual_security_level; /* minimum security_level for quals */
/* Note: qual_security_level is zero if there are no securityQuals */ /* Note: qual_security_level is zero if there are no securityQuals */
bool hasInheritedTarget; /* true if parse->resultRelation is an InheritanceKind inhTargetKind; /* indicates if the target relation is an
* inheritance child rel */ * inheritance child or partition or a
* partitioned table */
bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */ bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */
bool hasLateralRTEs; /* true if any RTEs are marked LATERAL */ bool hasLateralRTEs; /* true if any RTEs are marked LATERAL */
bool hasDeletedRTEs; /* true if any RTE was deleted from jointree */ bool hasDeletedRTEs; /* true if any RTE was deleted from jointree */
......
...@@ -71,6 +71,7 @@ extern PGDLLIMPORT bool enable_partitionwise_join; ...@@ -71,6 +71,7 @@ extern PGDLLIMPORT bool enable_partitionwise_join;
extern PGDLLIMPORT bool enable_partitionwise_aggregate; extern PGDLLIMPORT bool enable_partitionwise_aggregate;
extern PGDLLIMPORT bool enable_parallel_append; extern PGDLLIMPORT bool enable_parallel_append;
extern PGDLLIMPORT bool enable_parallel_hash; extern PGDLLIMPORT bool enable_parallel_hash;
extern PGDLLIMPORT bool enable_partition_pruning;
extern PGDLLIMPORT int constraint_exclusion; extern PGDLLIMPORT int constraint_exclusion;
extern double clamp_row_est(double nrows); extern double clamp_row_est(double nrows);
......
...@@ -2760,3 +2760,167 @@ explain (costs off) select * from pp_intrangepart where a = '(1,2)'::int4range; ...@@ -2760,3 +2760,167 @@ explain (costs off) select * from pp_intrangepart where a = '(1,2)'::int4range;
(2 rows) (2 rows)
drop table pp_intrangepart; drop table pp_intrangepart;
--
-- Ensure the enable_partition_prune GUC properly disables partition pruning.
--
create table pp_lp (a int, value int) partition by list (a);
create table pp_lp1 partition of pp_lp for values in(1);
create table pp_lp2 partition of pp_lp for values in(2);
explain (costs off) select * from pp_lp where a = 1;
QUERY PLAN
--------------------------
Append
-> Seq Scan on pp_lp1
Filter: (a = 1)
(3 rows)
explain (costs off) update pp_lp set value = 10 where a = 1;
QUERY PLAN
--------------------------
Update on pp_lp
Update on pp_lp1
-> Seq Scan on pp_lp1
Filter: (a = 1)
(4 rows)
explain (costs off) delete from pp_lp where a = 1;
QUERY PLAN
--------------------------
Delete on pp_lp
Delete on pp_lp1
-> Seq Scan on pp_lp1
Filter: (a = 1)
(4 rows)
set enable_partition_pruning = off;
set constraint_exclusion = 'partition'; -- this should not affect the result.
explain (costs off) select * from pp_lp where a = 1;
QUERY PLAN
--------------------------
Append
-> Seq Scan on pp_lp1
Filter: (a = 1)
-> Seq Scan on pp_lp2
Filter: (a = 1)
(5 rows)
explain (costs off) update pp_lp set value = 10 where a = 1;
QUERY PLAN
--------------------------
Update on pp_lp
Update on pp_lp1
Update on pp_lp2
-> Seq Scan on pp_lp1
Filter: (a = 1)
-> Seq Scan on pp_lp2
Filter: (a = 1)
(7 rows)
explain (costs off) delete from pp_lp where a = 1;
QUERY PLAN
--------------------------
Delete on pp_lp
Delete on pp_lp1
Delete on pp_lp2
-> Seq Scan on pp_lp1
Filter: (a = 1)
-> Seq Scan on pp_lp2
Filter: (a = 1)
(7 rows)
set constraint_exclusion = 'off'; -- this should not affect the result.
explain (costs off) select * from pp_lp where a = 1;
QUERY PLAN
--------------------------
Append
-> Seq Scan on pp_lp1
Filter: (a = 1)
-> Seq Scan on pp_lp2
Filter: (a = 1)
(5 rows)
explain (costs off) update pp_lp set value = 10 where a = 1;
QUERY PLAN
--------------------------
Update on pp_lp
Update on pp_lp1
Update on pp_lp2
-> Seq Scan on pp_lp1
Filter: (a = 1)
-> Seq Scan on pp_lp2
Filter: (a = 1)
(7 rows)
explain (costs off) delete from pp_lp where a = 1;
QUERY PLAN
--------------------------
Delete on pp_lp
Delete on pp_lp1
Delete on pp_lp2
-> Seq Scan on pp_lp1
Filter: (a = 1)
-> Seq Scan on pp_lp2
Filter: (a = 1)
(7 rows)
drop table pp_lp;
-- Ensure enable_partition_prune does not affect non-partitioned tables.
create table inh_lp (a int, value int);
create table inh_lp1 (a int, value int, check(a = 1)) inherits (inh_lp);
NOTICE: merging column "a" with inherited definition
NOTICE: merging column "value" with inherited definition
create table inh_lp2 (a int, value int, check(a = 2)) inherits (inh_lp);
NOTICE: merging column "a" with inherited definition
NOTICE: merging column "value" with inherited definition
set constraint_exclusion = 'partition';
-- inh_lp2 should be removed in the following 3 cases.
explain (costs off) select * from inh_lp where a = 1;
QUERY PLAN
---------------------------
Append
-> Seq Scan on inh_lp
Filter: (a = 1)
-> Seq Scan on inh_lp1
Filter: (a = 1)
(5 rows)
explain (costs off) update inh_lp set value = 10 where a = 1;
QUERY PLAN
---------------------------
Update on inh_lp
Update on inh_lp
Update on inh_lp1
-> Seq Scan on inh_lp
Filter: (a = 1)
-> Seq Scan on inh_lp1
Filter: (a = 1)
(7 rows)
explain (costs off) delete from inh_lp where a = 1;
QUERY PLAN
---------------------------
Delete on inh_lp
Delete on inh_lp
Delete on inh_lp1
-> Seq Scan on inh_lp
Filter: (a = 1)
-> Seq Scan on inh_lp1
Filter: (a = 1)
(7 rows)
-- Ensure we don't exclude normal relations when we only expect to exclude
-- inheritance children
explain (costs off) update inh_lp1 set value = 10 where a = 2;
QUERY PLAN
---------------------------
Update on inh_lp1
-> Seq Scan on inh_lp1
Filter: (a = 2)
(3 rows)
\set VERBOSITY terse \\ -- suppress cascade details
drop table inh_lp cascade;
NOTICE: drop cascades to 2 other objects
\set VERBOSITY default
reset enable_partition_pruning;
reset constraint_exclusion;
...@@ -83,12 +83,13 @@ select name, setting from pg_settings where name like 'enable%'; ...@@ -83,12 +83,13 @@ select name, setting from pg_settings where name like 'enable%';
enable_nestloop | on enable_nestloop | on
enable_parallel_append | on enable_parallel_append | on
enable_parallel_hash | on enable_parallel_hash | on
enable_partition_pruning | on
enable_partitionwise_aggregate | off enable_partitionwise_aggregate | off
enable_partitionwise_join | off enable_partitionwise_join | off
enable_seqscan | on enable_seqscan | on
enable_sort | on enable_sort | on
enable_tidscan | on enable_tidscan | on
(16 rows) (17 rows)
-- Test that the pg_timezone_names and pg_timezone_abbrevs views are -- Test that the pg_timezone_names and pg_timezone_abbrevs views are
-- more-or-less working. We can't test their contents in any great detail -- more-or-less working. We can't test their contents in any great detail
......
...@@ -723,3 +723,55 @@ create table pp_intrangepart2inf partition of pp_intrangepart for values in ('[2 ...@@ -723,3 +723,55 @@ create table pp_intrangepart2inf partition of pp_intrangepart for values in ('[2
explain (costs off) select * from pp_intrangepart where a = '[1,2]'::int4range; explain (costs off) select * from pp_intrangepart where a = '[1,2]'::int4range;
explain (costs off) select * from pp_intrangepart where a = '(1,2)'::int4range; explain (costs off) select * from pp_intrangepart where a = '(1,2)'::int4range;
drop table pp_intrangepart; drop table pp_intrangepart;
--
-- Ensure the enable_partition_prune GUC properly disables partition pruning.
--
create table pp_lp (a int, value int) partition by list (a);
create table pp_lp1 partition of pp_lp for values in(1);
create table pp_lp2 partition of pp_lp for values in(2);
explain (costs off) select * from pp_lp where a = 1;
explain (costs off) update pp_lp set value = 10 where a = 1;
explain (costs off) delete from pp_lp where a = 1;
set enable_partition_pruning = off;
set constraint_exclusion = 'partition'; -- this should not affect the result.
explain (costs off) select * from pp_lp where a = 1;
explain (costs off) update pp_lp set value = 10 where a = 1;
explain (costs off) delete from pp_lp where a = 1;
set constraint_exclusion = 'off'; -- this should not affect the result.
explain (costs off) select * from pp_lp where a = 1;
explain (costs off) update pp_lp set value = 10 where a = 1;
explain (costs off) delete from pp_lp where a = 1;
drop table pp_lp;
-- Ensure enable_partition_prune does not affect non-partitioned tables.
create table inh_lp (a int, value int);
create table inh_lp1 (a int, value int, check(a = 1)) inherits (inh_lp);
create table inh_lp2 (a int, value int, check(a = 2)) inherits (inh_lp);
set constraint_exclusion = 'partition';
-- inh_lp2 should be removed in the following 3 cases.
explain (costs off) select * from inh_lp where a = 1;
explain (costs off) update inh_lp set value = 10 where a = 1;
explain (costs off) delete from inh_lp where a = 1;
-- Ensure we don't exclude normal relations when we only expect to exclude
-- inheritance children
explain (costs off) update inh_lp1 set value = 10 where a = 2;
\set VERBOSITY terse \\ -- suppress cascade details
drop table inh_lp cascade;
\set VERBOSITY default
reset enable_partition_pruning;
reset constraint_exclusion;
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