mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
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
This commit is contained in:
@ -2760,3 +2760,167 @@ explain (costs off) select * from pp_intrangepart where a = '(1,2)'::int4range;
|
||||
(2 rows)
|
||||
|
||||
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%';
|
||||
enable_nestloop | on
|
||||
enable_parallel_append | on
|
||||
enable_parallel_hash | on
|
||||
enable_partition_pruning | on
|
||||
enable_partitionwise_aggregate | off
|
||||
enable_partitionwise_join | off
|
||||
enable_seqscan | on
|
||||
enable_sort | on
|
||||
enable_tidscan | on
|
||||
(16 rows)
|
||||
(17 rows)
|
||||
|
||||
-- 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
|
||||
|
@ -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;
|
||||
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;
|
||||
|
Reference in New Issue
Block a user