Clean up handling of constraint_exclusion and enable_partition_pruning.
The interaction of these parameters was a bit confused/confusing, and in fact v11 entirely misses the opportunity to apply partition constraints when a partition is accessed directly (rather than indirectly from its parent). In HEAD, establish the principle that enable_partition_pruning controls partition pruning and nothing else. When accessing a partition via its parent, we do partition pruning (if enabled by enable_partition_pruning) and then there is no need to consider partition constraints in the constraint_exclusion logic. When accessing a partition directly, its partition constraints are applied by the constraint_exclusion logic, only if constraint_exclusion = on. In v11, we can't have such a clean division of these GUCs' effects, partly because we don't want to break compatibility too much in a released branch, and partly because the clean coding requires inheritance_planner to have applied partition pruning to a partitioned target table, which it doesn't in v11. However, we can tweak things enough to cover the missed case, which seems like a good idea since it's potentially a performance regression from v10. This patch keeps v11's previous behavior in which enable_partition_pruning overrides constraint_exclusion for an inherited target table, though. In HEAD, also teach relation_excluded_by_constraints that it's okay to use inheritable constraints when trying to prune a traditional inheritance tree. This might not be thought worthy of effort given that that feature is semi-deprecated now, but we have enough infrastructure that it only takes a couple more lines of code to do it correctly. Amit Langote and Tom Lane Discussion: https://postgr.es/m/9813f079-f16b-61c8-9ab7-4363cab28d80@lab.ntt.co.jp Discussion: https://postgr.es/m/29069.1555970894@sss.pgh.pa.us
This commit is contained in:
parent
14323493dd
commit
11ea45ffec
@ -4410,10 +4410,11 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
|
|||||||
The allowed values of <varname>constraint_exclusion</varname> are
|
The allowed values of <varname>constraint_exclusion</varname> are
|
||||||
<literal>on</literal> (examine constraints for all tables),
|
<literal>on</literal> (examine constraints for all tables),
|
||||||
<literal>off</literal> (never examine constraints), and
|
<literal>off</literal> (never examine constraints), and
|
||||||
<literal>partition</literal> (examine constraints only for inheritance child
|
<literal>partition</literal> (examine constraints only for inheritance
|
||||||
tables and <literal>UNION ALL</literal> subqueries).
|
child 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 tables to improve performance.
|
It is often used with traditional inheritance trees to improve
|
||||||
|
performance.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -4437,15 +4438,19 @@ 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 via
|
only for cases that are often used to implement table partitioning via
|
||||||
inheritance tables. Turning it on for all tables imposes extra
|
inheritance trees. Turning it on for all tables imposes extra
|
||||||
planning overhead that is quite noticeable on simple queries, and most
|
planning overhead that is quite noticeable on simple queries, and most
|
||||||
often will yield no benefit for simple queries. If you have no
|
often will yield no benefit for simple queries. If you have no
|
||||||
inheritance partitioned tables you might prefer to turn it off entirely.
|
tables that are partitioned using traditional inheritance, you might
|
||||||
|
prefer to turn it off entirely. (Note that the equivalent feature for
|
||||||
|
partitioned tables is controlled by a separate parameter,
|
||||||
|
<xref linkend="guc-enable-partition-pruning"/>.)
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Refer to <xref linkend="ddl-partitioning-constraint-exclusion"/> for
|
Refer to <xref linkend="ddl-partitioning-constraint-exclusion"/> for
|
||||||
more information on using constraint exclusion and partitioning.
|
more information on using constraint exclusion to implement
|
||||||
|
partitioning.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -3918,22 +3918,11 @@ EXPLAIN SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01';
|
|||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
Currently, pruning of partitions during the planning of an
|
Execution-time partition pruning currently only occurs for the
|
||||||
<command>UPDATE</command> or <command>DELETE</command> command is
|
<literal>Append</literal> node type, not
|
||||||
implemented using the constraint exclusion method (however, it is
|
for <literal>MergeAppend</literal> or <literal>ModifyTable</literal>
|
||||||
controlled by the <literal>enable_partition_pruning</literal> rather than
|
nodes. That is likely to be changed in a future release of
|
||||||
<literal>constraint_exclusion</literal>) — see the following section
|
<productname>PostgreSQL</productname>.
|
||||||
for details and caveats that apply.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Also, execution-time partition pruning currently only occurs for the
|
|
||||||
<literal>Append</literal> node type, not <literal>MergeAppend</literal>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Both of these behaviors are likely to be changed in a future release
|
|
||||||
of <productname>PostgreSQL</productname>.
|
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
@ -1324,8 +1324,9 @@ inheritance_planner(PlannerInfo *root)
|
|||||||
parent_rte->securityQuals = NIL;
|
parent_rte->securityQuals = NIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mark whether we're planning a query to a partitioned table or an
|
* HACK: setting this to a value other than INHKIND_NONE signals to
|
||||||
* inheritance parent.
|
* relation_excluded_by_constraints() to treat the result relation as
|
||||||
|
* being an appendrel member.
|
||||||
*/
|
*/
|
||||||
subroot->inhTargetKind =
|
subroot->inhTargetKind =
|
||||||
partitioned_relids ? INHKIND_PARTITIONED : INHKIND_INHERITED;
|
partitioned_relids ? INHKIND_PARTITIONED : INHKIND_INHERITED;
|
||||||
|
@ -66,7 +66,9 @@ static bool infer_collation_opclass_match(InferenceElem *elem, Relation idxRel,
|
|||||||
static int32 get_rel_data_width(Relation rel, int32 *attr_widths);
|
static int32 get_rel_data_width(Relation rel, int32 *attr_widths);
|
||||||
static List *get_relation_constraints(PlannerInfo *root,
|
static List *get_relation_constraints(PlannerInfo *root,
|
||||||
Oid relationObjectId, RelOptInfo *rel,
|
Oid relationObjectId, RelOptInfo *rel,
|
||||||
bool include_notnull);
|
bool include_noinherit,
|
||||||
|
bool include_notnull,
|
||||||
|
bool include_partition);
|
||||||
static List *build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
|
static List *build_index_tlist(PlannerInfo *root, IndexOptInfo *index,
|
||||||
Relation heapRelation);
|
Relation heapRelation);
|
||||||
static List *get_relation_statistics(RelOptInfo *rel, Relation relation);
|
static List *get_relation_statistics(RelOptInfo *rel, Relation relation);
|
||||||
@ -1157,16 +1159,22 @@ get_relation_data_width(Oid relid, int32 *attr_widths)
|
|||||||
/*
|
/*
|
||||||
* get_relation_constraints
|
* get_relation_constraints
|
||||||
*
|
*
|
||||||
* Retrieve the validated CHECK constraint expressions of the given relation.
|
* Retrieve the applicable constraint expressions of the given relation.
|
||||||
*
|
*
|
||||||
* Returns a List (possibly empty) of constraint expressions. Each one
|
* Returns a List (possibly empty) of constraint expressions. Each one
|
||||||
* has been canonicalized, and its Vars are changed to have the varno
|
* has been canonicalized, and its Vars are changed to have the varno
|
||||||
* indicated by rel->relid. This allows the expressions to be easily
|
* indicated by rel->relid. This allows the expressions to be easily
|
||||||
* compared to expressions taken from WHERE.
|
* compared to expressions taken from WHERE.
|
||||||
*
|
*
|
||||||
|
* If include_noinherit is true, it's okay to include constraints that
|
||||||
|
* are marked NO INHERIT.
|
||||||
|
*
|
||||||
* If include_notnull is true, "col IS NOT NULL" expressions are generated
|
* If include_notnull is true, "col IS NOT NULL" expressions are generated
|
||||||
* and added to the result for each column that's marked attnotnull.
|
* and added to the result for each column that's marked attnotnull.
|
||||||
*
|
*
|
||||||
|
* If include_partition is true, and the relation is a partition,
|
||||||
|
* also include the partitioning constraints.
|
||||||
|
*
|
||||||
* Note: at present this is invoked at most once per relation per planner
|
* Note: at present this is invoked at most once per relation per planner
|
||||||
* run, and in many cases it won't be invoked at all, so there seems no
|
* run, and in many cases it won't be invoked at all, so there seems no
|
||||||
* point in caching the data in RelOptInfo.
|
* point in caching the data in RelOptInfo.
|
||||||
@ -1174,7 +1182,9 @@ get_relation_data_width(Oid relid, int32 *attr_widths)
|
|||||||
static List *
|
static List *
|
||||||
get_relation_constraints(PlannerInfo *root,
|
get_relation_constraints(PlannerInfo *root,
|
||||||
Oid relationObjectId, RelOptInfo *rel,
|
Oid relationObjectId, RelOptInfo *rel,
|
||||||
bool include_notnull)
|
bool include_noinherit,
|
||||||
|
bool include_notnull,
|
||||||
|
bool include_partition)
|
||||||
{
|
{
|
||||||
List *result = NIL;
|
List *result = NIL;
|
||||||
Index varno = rel->relid;
|
Index varno = rel->relid;
|
||||||
@ -1198,10 +1208,13 @@ get_relation_constraints(PlannerInfo *root,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* If this constraint hasn't been fully validated yet, we must
|
* If this constraint hasn't been fully validated yet, we must
|
||||||
* ignore it here.
|
* ignore it here. Also ignore if NO INHERIT and we weren't told
|
||||||
|
* that that's safe.
|
||||||
*/
|
*/
|
||||||
if (!constr->check[i].ccvalid)
|
if (!constr->check[i].ccvalid)
|
||||||
continue;
|
continue;
|
||||||
|
if (constr->check[i].ccnoinherit && !include_noinherit)
|
||||||
|
continue;
|
||||||
|
|
||||||
cexpr = stringToNode(constr->check[i].ccbin);
|
cexpr = stringToNode(constr->check[i].ccbin);
|
||||||
|
|
||||||
@ -1266,13 +1279,9 @@ get_relation_constraints(PlannerInfo *root,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Append partition predicates, if any.
|
* Add partitioning constraints, if requested.
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
if (enable_partition_pruning && root->parse->commandType != CMD_SELECT)
|
if (include_partition && relation->rd_rel->relispartition)
|
||||||
{
|
{
|
||||||
List *pcqual = RelationGetPartitionQual(relation);
|
List *pcqual = RelationGetPartitionQual(relation);
|
||||||
|
|
||||||
@ -1377,7 +1386,7 @@ get_relation_statistics(RelOptInfo *rel, Relation relation)
|
|||||||
*
|
*
|
||||||
* Detect whether the relation need not be scanned because it has either
|
* Detect whether the relation need not be scanned because it has either
|
||||||
* self-inconsistent restrictions, or restrictions inconsistent with the
|
* self-inconsistent restrictions, or restrictions inconsistent with the
|
||||||
* relation's validated CHECK constraints.
|
* relation's applicable constraints.
|
||||||
*
|
*
|
||||||
* Note: this examines only rel->relid, rel->reloptkind, and
|
* Note: this examines only rel->relid, rel->reloptkind, and
|
||||||
* rel->baserestrictinfo; therefore it can be called before filling in
|
* rel->baserestrictinfo; therefore it can be called before filling in
|
||||||
@ -1387,6 +1396,9 @@ bool
|
|||||||
relation_excluded_by_constraints(PlannerInfo *root,
|
relation_excluded_by_constraints(PlannerInfo *root,
|
||||||
RelOptInfo *rel, RangeTblEntry *rte)
|
RelOptInfo *rel, RangeTblEntry *rte)
|
||||||
{
|
{
|
||||||
|
bool include_noinherit;
|
||||||
|
bool include_notnull;
|
||||||
|
bool include_partition = false;
|
||||||
List *safe_restrictions;
|
List *safe_restrictions;
|
||||||
List *constraint_pred;
|
List *constraint_pred;
|
||||||
List *safe_constraints;
|
List *safe_constraints;
|
||||||
@ -1395,6 +1407,13 @@ relation_excluded_by_constraints(PlannerInfo *root,
|
|||||||
/* As of now, constraint exclusion works only with simple relations. */
|
/* As of now, constraint exclusion works only with simple relations. */
|
||||||
Assert(IS_SIMPLE_REL(rel));
|
Assert(IS_SIMPLE_REL(rel));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there are no base restriction clauses, we have no hope of proving
|
||||||
|
* anything below, so fall out quickly.
|
||||||
|
*/
|
||||||
|
if (rel->baserestrictinfo == NIL)
|
||||||
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Regardless of the setting of constraint_exclusion, detect
|
* Regardless of the setting of constraint_exclusion, detect
|
||||||
* constant-FALSE-or-NULL restriction clauses. Because const-folding will
|
* constant-FALSE-or-NULL restriction clauses. Because const-folding will
|
||||||
@ -1415,6 +1434,17 @@ relation_excluded_by_constraints(PlannerInfo *root,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Partition pruning will not have been applied to an inherited target
|
||||||
|
* relation, so if enable_partition_pruning is true, force consideration
|
||||||
|
* of the rel's partition constraints. (Thus constraint_exclusion will be
|
||||||
|
* effectively forced 'on' for this case. This is done better in v12.)
|
||||||
|
*/
|
||||||
|
if (enable_partition_pruning &&
|
||||||
|
rel->relid == root->parse->resultRelation &&
|
||||||
|
root->inhTargetKind != INHKIND_NONE)
|
||||||
|
include_partition = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip further tests, depending on constraint_exclusion.
|
* Skip further tests, depending on constraint_exclusion.
|
||||||
*/
|
*/
|
||||||
@ -1423,15 +1453,10 @@ relation_excluded_by_constraints(PlannerInfo *root,
|
|||||||
case CONSTRAINT_EXCLUSION_OFF:
|
case CONSTRAINT_EXCLUSION_OFF:
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't prune if feature turned off -- except if the relation is
|
* In 'off' mode, never make any further tests, except if forcing
|
||||||
* a partition. While partprune.c-style partition pruning is not
|
* include_partition.
|
||||||
* 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)
|
if (include_partition)
|
||||||
break;
|
break;
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -1439,17 +1464,32 @@ relation_excluded_by_constraints(PlannerInfo *root,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* When constraint_exclusion is set to 'partition' we only handle
|
* When constraint_exclusion is set to 'partition' we only handle
|
||||||
* OTHER_MEMBER_RELs, or BASERELs in cases where the result target
|
* appendrel members. Normally, they are RELOPT_OTHER_MEMBER_REL
|
||||||
* is an inheritance parent or a partitioned table.
|
* relations, but we also consider inherited target relations as
|
||||||
|
* appendrel members for the purposes of constraint exclusion.
|
||||||
|
*
|
||||||
|
* In the former case, partition pruning was already applied, so
|
||||||
|
* there is no need to consider the rel's partition constraints
|
||||||
|
* here. In the latter case, we already set include_partition
|
||||||
|
* properly (i.e., do it if enable_partition_pruning).
|
||||||
*/
|
*/
|
||||||
if ((rel->reloptkind != RELOPT_OTHER_MEMBER_REL) &&
|
if (rel->reloptkind == RELOPT_OTHER_MEMBER_REL ||
|
||||||
!(rel->reloptkind == RELOPT_BASEREL &&
|
(rel->relid == root->parse->resultRelation &&
|
||||||
root->inhTargetKind != INHKIND_NONE &&
|
root->inhTargetKind != INHKIND_NONE))
|
||||||
rel->relid == root->parse->resultRelation))
|
break; /* appendrel member, so process it */
|
||||||
return false;
|
return false;
|
||||||
break;
|
|
||||||
|
|
||||||
case CONSTRAINT_EXCLUSION_ON:
|
case CONSTRAINT_EXCLUSION_ON:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In 'on' mode, always apply constraint exclusion. If we are
|
||||||
|
* considering a baserel that is a partition (i.e., it was
|
||||||
|
* directly named rather than expanded from a parent table), then
|
||||||
|
* its partition constraints haven't been considered yet, so
|
||||||
|
* include them in the processing here.
|
||||||
|
*/
|
||||||
|
if (rel->reloptkind == RELOPT_BASEREL)
|
||||||
|
include_partition = true;
|
||||||
break; /* always try to exclude */
|
break; /* always try to exclude */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1478,24 +1518,40 @@ relation_excluded_by_constraints(PlannerInfo *root,
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only plain relations have constraints. In a partitioning hierarchy,
|
* Only plain relations have constraints, so stop here for other rtekinds.
|
||||||
* but not with regular table inheritance, it's OK to assume that any
|
|
||||||
* constraints that hold for the parent also hold for every child; for
|
|
||||||
* instance, table inheritance allows the parent to have constraints
|
|
||||||
* marked NO INHERIT, but table partitioning does not. We choose to check
|
|
||||||
* whether the partitioning parents can be excluded here; doing so
|
|
||||||
* consumes some cycles, but potentially saves us the work of excluding
|
|
||||||
* each child individually.
|
|
||||||
*/
|
*/
|
||||||
if (rte->rtekind != RTE_RELATION ||
|
if (rte->rtekind != RTE_RELATION)
|
||||||
(rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OK to fetch the constraint expressions. Include "col IS NOT NULL"
|
* In a partitioning hierarchy, but not with regular table inheritance,
|
||||||
* expressions for attnotnull columns, in case we can refute those.
|
* it's OK to assume that any constraints that hold for the parent also
|
||||||
|
* hold for every child; for instance, table inheritance allows the parent
|
||||||
|
* to have constraints marked NO INHERIT, but table partitioning does not.
|
||||||
|
* We choose to check whether the partitioning parents can be excluded
|
||||||
|
* here; doing so consumes some cycles, but potentially saves us the work
|
||||||
|
* of excluding each child individually.
|
||||||
|
*
|
||||||
|
* This is unnecessarily stupid, but making it smarter seems out of scope
|
||||||
|
* for v11.
|
||||||
*/
|
*/
|
||||||
constraint_pred = get_relation_constraints(root, rte->relid, rel, true);
|
if (rte->inh && rte->relkind != RELKIND_PARTITIONED_TABLE)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Given the above restriction, we can always include NO INHERIT and NOT
|
||||||
|
* NULL constraints.
|
||||||
|
*/
|
||||||
|
include_noinherit = true;
|
||||||
|
include_notnull = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fetch the appropriate set of constraint expressions.
|
||||||
|
*/
|
||||||
|
constraint_pred = get_relation_constraints(root, rte->relid, rel,
|
||||||
|
include_noinherit,
|
||||||
|
include_notnull,
|
||||||
|
include_partition);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We do not currently enforce that CHECK constraints contain only
|
* We do not currently enforce that CHECK constraints contain only
|
||||||
|
@ -3417,4 +3417,46 @@ select * from listp where a = (select 2) and b <> 10;
|
|||||||
Filter: ((b <> 10) AND (a = $0))
|
Filter: ((b <> 10) AND (a = $0))
|
||||||
(5 rows)
|
(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;
|
||||||
|
-- setting constraint_exclusion to 'partition' disables exclusion
|
||||||
|
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) update listp1 set a = 1 where a = 2;
|
||||||
|
QUERY PLAN
|
||||||
|
--------------------------
|
||||||
|
Update on listp1
|
||||||
|
-> Seq Scan on listp1
|
||||||
|
Filter: (a = 2)
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
-- constraint exclusion enabled
|
||||||
|
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) update listp1 set a = 1 where a = 2;
|
||||||
|
QUERY PLAN
|
||||||
|
--------------------------------
|
||||||
|
Update on listp1
|
||||||
|
-> Result
|
||||||
|
One-Time Filter: false
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
reset constraint_exclusion;
|
||||||
|
reset enable_partition_pruning;
|
||||||
drop table listp;
|
drop table listp;
|
||||||
|
@ -899,4 +899,24 @@ create table listp2_10 partition of listp2 for values in (10);
|
|||||||
explain (analyze, costs off, summary off, timing off)
|
explain (analyze, costs off, summary off, timing off)
|
||||||
select * from listp where a = (select 2) and b <> 10;
|
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;
|
||||||
|
|
||||||
|
-- setting constraint_exclusion to 'partition' disables exclusion
|
||||||
|
set constraint_exclusion to 'partition';
|
||||||
|
explain (costs off) select * from listp1 where a = 2;
|
||||||
|
explain (costs off) update listp1 set a = 1 where a = 2;
|
||||||
|
-- constraint exclusion enabled
|
||||||
|
set constraint_exclusion to 'on';
|
||||||
|
explain (costs off) select * from listp1 where a = 2;
|
||||||
|
explain (costs off) update listp1 set a = 1 where a = 2;
|
||||||
|
|
||||||
|
reset constraint_exclusion;
|
||||||
|
reset enable_partition_pruning;
|
||||||
|
|
||||||
drop table listp;
|
drop table listp;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user