@@ -2946,7 +2946,7 @@ VALUES ('Albany', NULL, NULL, 'NY');
2946
2946
divide a table into pieces called partitions. The table that is divided
2947
2947
is referred to as a <firstterm>partitioned table</firstterm>. The
2948
2948
specification consists of the <firstterm>partitioning method</firstterm>
2949
- and a list of columns or expressions to be used as the
2949
+ and a list of columns or expressions to be used as the
2950
2950
<firstterm>partition key</firstterm>.
2951
2951
</para>
2952
2952
@@ -3759,105 +3759,211 @@ ANALYZE measurement;
3759
3759
</sect3>
3760
3760
</sect2>
3761
3761
3762
- <sect2 id="ddl-partitioning-constraint-exclusion ">
3763
- <title>Partitioning and Constraint Exclusion </title>
3762
+ <sect2 id="ddl-partition-pruning ">
3763
+ <title>Partition Pruning </title>
3764
3764
3765
3765
<indexterm>
3766
- <primary>constraint exclusion </primary>
3766
+ <primary>partition pruning </primary>
3767
3767
</indexterm>
3768
3768
3769
3769
<para>
3770
- <firstterm>Constraint exclusion</firstterm> is a query optimization technique
3771
- that improves performance for partitioned tables defined in the
3772
- fashion described above (both declaratively partitioned tables and those
3773
- implemented using inheritance). As an example:
3770
+ <firstterm>Partition pruning</firstterm> is a query optimization technique
3771
+ that improves performance for partitioned tables. As an example:
3774
3772
3775
3773
<programlisting>
3776
- SET constraint_exclusion = on;
3774
+ SET enable_partition_pruning = on; -- the default
3777
3775
SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01';
3778
3776
</programlisting>
3779
3777
3780
- Without constraint exclusion , the above query would scan each of
3781
- the partitions of the <structname>measurement</structname> table. With constraint
3782
- exclusion enabled, the planner will examine the constraints of each
3783
- partition and try to prove that the partition need not
3778
+ Without partition pruning , the above query would scan each of the
3779
+ partitions of the <structname>measurement</structname> table. With
3780
+ partition pruning enabled, the planner will examine the definition
3781
+ of each partition and prove that the partition need not
3784
3782
be scanned because it could not contain any rows meeting the query's
3785
3783
<literal>WHERE</literal> clause. When the planner can prove this, it
3786
- excludes the partition from the query plan.
3784
+ excludes (<firstterm>prunes</firstterm>) the partition from the query
3785
+ plan.
3787
3786
</para>
3788
3787
3789
3788
<para>
3790
- You can use the <command>EXPLAIN</command> command to show the difference
3791
- between a plan with <varname>constraint_exclusion</varname> on and a plan
3792
- with it off. A typical unoptimized plan for this type of table setup is:
3793
-
3789
+ You can use the <command>EXPLAIN</command> command to show the
3790
+ difference between a plan whose partitions have been pruned from one
3791
+ whose partitions haven't, by using the
3792
+ <xref linkend="guc-enable-partition-pruning"/> configuration
3793
+ parameter. A typical unoptimized plan for this type of table setup
3794
+ is:
3794
3795
<programlisting>
3795
- SET constraint_exclusion = off;
3796
+ SET enable_partition_pruning = off;
3796
3797
EXPLAIN SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01';
3797
-
3798
- QUERY PLAN
3799
- -----------------------------------------------------------------------------------------------
3800
- Aggregate (cost=158.66..158.68 rows=1 width=0)
3801
- -> Append (cost=0.00..151.88 rows=2715 width=0)
3802
- -> Seq Scan on measurement (cost=0.00..30.38 rows=543 width=0)
3803
- Filter: (logdate >= '2008-01-01'::date)
3804
- -> Seq Scan on measurement_y2006m02 measurement (cost=0.00..30.38 rows=543 width=0)
3798
+ QUERY PLAN
3799
+ ───────────────────────────────────────────────────────────────────────────────────
3800
+ Aggregate (cost=188.76..188.77 rows=1 width=8)
3801
+ -> Append (cost=0.00..181.05 rows=3085 width=0)
3802
+ -> Seq Scan on measurement_y2006m02 (cost=0.00..33.12 rows=617 width=0)
3805
3803
Filter: (logdate >= '2008-01-01'::date)
3806
- -> Seq Scan on measurement_y2006m03 measurement (cost=0.00..30.38 rows=543 width=0)
3804
+ -> Seq Scan on measurement_y2006m03 (cost=0.00..33.12 rows=617 width=0)
3807
3805
Filter: (logdate >= '2008-01-01'::date)
3808
3806
...
3809
- -> Seq Scan on measurement_y2007m12 measurement (cost=0.00..30.38 rows=543 width=0)
3807
+ -> Seq Scan on measurement_y2007m11 (cost=0.00..33.12 rows=617 width=0)
3810
3808
Filter: (logdate >= '2008-01-01'::date)
3811
- -> Seq Scan on measurement_y2008m01 measurement (cost=0.00..30.38 rows=543 width=0)
3809
+ -> Seq Scan on measurement_y2007m12 (cost=0.00..33.12 rows=617 width=0)
3810
+ Filter: (logdate >= '2008-01-01'::date)
3811
+ -> Seq Scan on measurement_y2008m01 (cost=0.00..33.12 rows=617 width=0)
3812
3812
Filter: (logdate >= '2008-01-01'::date)
3813
3813
</programlisting>
3814
3814
3815
3815
Some or all of the partitions might use index scans instead of
3816
3816
full-table sequential scans, but the point here is that there
3817
3817
is no need to scan the older partitions at all to answer this query.
3818
- When we enable constraint exclusion , we get a significantly
3818
+ When we enable partition pruning , we get a significantly
3819
3819
cheaper plan that will deliver the same answer:
3820
-
3821
3820
<programlisting>
3822
- SET constraint_exclusion = on;
3821
+ SET enable_partition_pruning = on;
3823
3822
EXPLAIN SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01';
3824
- QUERY PLAN
3825
- -----------------------------------------------------------------------------------------------
3826
- Aggregate (cost=63.47..63.48 rows=1 width=0)
3827
- -> Append (cost=0.00..60.75 rows=1086 width=0)
3828
- -> Seq Scan on measurement (cost=0.00..30.38 rows=543 width=0)
3829
- Filter: (logdate >= '2008-01-01'::date)
3830
- -> Seq Scan on measurement_y2008m01 measurement (cost=0.00..30.38 rows=543 width=0)
3823
+ QUERY PLAN
3824
+ ───────────────────────────────────────────────────────────────────────────────────
3825
+ Aggregate (cost=37.75..37.76 rows=1 width=8)
3826
+ -> Append (cost=0.00..36.21 rows=617 width=0)
3827
+ -> Seq Scan on measurement_y2008m01 (cost=0.00..33.12 rows=617 width=0)
3831
3828
Filter: (logdate >= '2008-01-01'::date)
3832
3829
</programlisting>
3833
3830
</para>
3834
3831
3835
3832
<para>
3836
- Note that constraint exclusion is driven only by <literal>CHECK</literal>
3837
- constraints, not by the presence of indexes. Therefore it isn't
3838
- necessary to define indexes on the key columns. Whether an index
3839
- needs to be created for a given partition depends on whether you
3840
- expect that queries that scan the partition will generally scan
3841
- a large part of the partition or just a small part. An index will
3842
- be helpful in the latter case but not the former.
3833
+ Note that partition pruning is driven only by the constraints defined
3834
+ implicitly by the partition keys, not by the presence of indexes.
3835
+ Therefore it isn't necessary to define indexes on the key columns.
3836
+ Whether an index needs to be created for a given partition depends on
3837
+ whether you expect that queries that scan the partition will
3838
+ generally scan a large part of the partition or just a small part.
3839
+ An index will be helpful in the latter case but not the former.
3840
+ </para>
3841
+
3842
+ <para>
3843
+ Partition pruning can be performed not only during the planning of a
3844
+ given query, but also during its execution. This is useful as it can
3845
+ allow more partitions to be pruned when clauses contain expressions
3846
+ whose values are not known at query planning time; for example,
3847
+ parameters defined in a <command>PREPARE</command> statement, using a
3848
+ value obtained from a subquery or using a parameterized value on the
3849
+ inner side of a nested loop join. Partition pruning during execution
3850
+ can be performed at any of the following times:
3851
+
3852
+ <itemizedlist>
3853
+ <listitem>
3854
+ <para>
3855
+ During initialization of the query plan. Partition pruning can be
3856
+ performed here for parameter values which are known during the
3857
+ initialization phase of execution. Partitions which are pruned
3858
+ during this stage will not show up in the query's
3859
+ <command>EXPLAIN</command> or <command>EXPLAIN ANALYZE</command>.
3860
+ It is possible to determine the number of partitions which were
3861
+ removed during this phase by observing the
3862
+ <quote>Subplans Removed</quote> property in the
3863
+ <command>EXPLAIN</command> output.
3864
+ </para>
3865
+ </listitem>
3866
+
3867
+ <listitem>
3868
+ <para>
3869
+ During actual execution of the query plan. Partition pruning may
3870
+ also be performed here to remove partitions using values which are
3871
+ only known during actual query execution. This includes values
3872
+ from subqueries and values from execution-time parameters such as
3873
+ those from parameterized nested loop joins. Since the value of
3874
+ these parameters may change many times during the execution of the
3875
+ query, partition pruning is performed whenever one of the
3876
+ execution parameters being used by partition pruning changes.
3877
+ Determining if partitions were pruned during this phase requires
3878
+ careful inspection of the <literal>nloops</literal> property in
3879
+ the <command>EXPLAIN ANALYZE</command> output.
3880
+ </para>
3881
+ </listitem>
3882
+ </itemizedlist>
3883
+ </para>
3884
+
3885
+ <para>
3886
+ Partition pruning can be disabled using the
3887
+ <xref linkend="guc-enable-partition-pruning"/> setting.
3888
+ </para>
3889
+
3890
+ <note>
3891
+ <para>
3892
+ Currently, pruning of partitions during the planning of an
3893
+ <command>UPDATE</command> or <command>DELETE</command> command is
3894
+ implemented using the constraint exclusion method (however, it is
3895
+ still ruled by the <literal>enable_partition_pruning</literal>
3896
+ setting instead of <literal>constraint_exclusion</literal>) —
3897
+ see the next section for details and caveats that apply.
3898
+ </para>
3899
+
3900
+ <para>
3901
+ Also, execution-time partition pruning currently only occurs for the
3902
+ <literal>Append</literal> node type, not <literal>MergeAppend</literal>.
3903
+ </para>
3904
+
3905
+ <para>
3906
+ Both of these behaviors are likely to be changed in a future release
3907
+ of <productname>PostgreSQL</productname>.
3908
+ </para>
3909
+ </note>
3910
+ </sect2>
3911
+
3912
+ <sect2 id="ddl-partitioning-constraint-exclusion">
3913
+ <title>Partitioning and Constraint Exclusion</title>
3914
+
3915
+ <indexterm>
3916
+ <primary>constraint exclusion</primary>
3917
+ </indexterm>
3918
+
3919
+ <para>
3920
+ <firstterm>Constraint exclusion</firstterm> is a query optimization
3921
+ technique similar to partition pruning. While it is primarily used
3922
+ for partitioned tables using the legacy inheritance method, it can be
3923
+ used for other purposes, including with declarative partitioning.
3924
+ </para>
3925
+
3926
+ <para>
3927
+ Constraint exclusion works in a very similar way to partition
3928
+ pruning, except that it uses each table's <literal>CHECK</literal>
3929
+ constraints — which gives it its name — whereas partition
3930
+ pruning uses the table's partitioning constraint, which exists only in
3931
+ the case of declarative partitioning. Another difference is that it
3932
+ is only applied at plan time; there is no attempt to remove
3933
+ partitions at execution time.
3934
+ </para>
3935
+
3936
+ <para>
3937
+ The fact that constraint exclusion uses <literal>CHECK</literal>
3938
+ constraints, which makes it slow compared to partition pruning, can
3939
+ sometimes be used as an advantage: because constraints can be defined
3940
+ even on declaratively-partitioned tables, in addition to the internal
3941
+ partitioning constraints, and only constraint exclusion would be able
3942
+ to elide certain partitions from the query plan using those.
3843
3943
</para>
3844
3944
3845
3945
<para>
3846
3946
The default (and recommended) setting of
3847
- <xref linkend="guc-constraint-exclusion"/> is actually neither
3947
+ <xref linkend="guc-constraint-exclusion"/> is neither
3848
3948
<literal>on</literal> nor <literal>off</literal>, but an intermediate setting
3849
3949
called <literal>partition</literal>, which causes the technique to be
3850
- applied only to queries that are likely to be working on partitioned
3950
+ applied only to queries that are likely to be working on inheritance partitioned
3851
3951
tables. The <literal>on</literal> setting causes the planner to examine
3852
3952
<literal>CHECK</literal> constraints in all queries, even simple ones that
3853
3953
are unlikely to benefit.
3854
3954
</para>
3855
3955
3856
3956
<para>
3857
- The following caveats apply to constraint exclusion, which is used by
3858
- both inheritance and partitioned tables:
3957
+ The following caveats apply to constraint exclusion:
3859
3958
3860
3959
<itemizedlist>
3960
+ <listitem>
3961
+ <para>
3962
+ Constraint exclusion is only applied during query planning; it is
3963
+ not applied at execution time like partition pruning does.
3964
+ </para>
3965
+ </listitem>
3966
+
3861
3967
<listitem>
3862
3968
<para>
3863
3969
Constraint exclusion only works when the query's <literal>WHERE</literal>
@@ -3877,21 +3983,18 @@ EXPLAIN SELECT count(*) FROM measurement WHERE logdate >= DATE '2008-01-01';
3877
3983
range tests for range partitioning, as illustrated in the preceding
3878
3984
examples. A good rule of thumb is that partitioning constraints should
3879
3985
contain only comparisons of the partitioning column(s) to constants
3880
- using B-tree-indexable operators, which applies even to partitioned
3881
- tables, because only B-tree-indexable column(s) are allowed in the
3882
- partition key. (This is not a problem when using declarative
3883
- partitioning, since the automatically generated constraints are simple
3884
- enough to be understood by the planner.)
3986
+ using B-tree-indexable operators, because only B-tree-indexable
3987
+ column(s) are allowed in the partition key.
3885
3988
</para>
3886
3989
</listitem>
3887
3990
3888
3991
<listitem>
3889
3992
<para>
3890
3993
All constraints on all partitions of the master table are examined
3891
3994
during constraint exclusion, so large numbers of partitions are likely
3892
- to increase query planning time considerably. Partitioning using
3893
- these techniques will work well with up to perhaps a hundred partitions;
3894
- don't try to use many thousands of partitions.
3995
+ to increase query planning time considerably. So the legacy
3996
+ inheritance based partitioning will work well with up to perhaps a
3997
+ hundred partitions; don't try to use many thousands of partitions.
3895
3998
</para>
3896
3999
</listitem>
3897
4000
0 commit comments