mirror of
https://github.com/postgres/postgres.git
synced 2025-07-12 21:01:52 +03:00
Allow ordered partition scans in more cases
959d00e9d
added the ability to make use of an Append node instead of a MergeAppend when we wanted to perform a scan of a partitioned table and the required sort order was the same as the partitioned keys and the partitioned table was defined in such a way that earlier partitions were guaranteed to only contain lower-order values than later partitions. However, previously we didn't allow these ordered partition scans for LIST partitioned table when there were any partitions that allowed multiple Datums. This was a very cheap check to make and we could likely have done a little better by checking if there were interleaved partitions, but at the time we didn't have visibility about which partitions were pruned, so we still may have disallowed cases where all interleaved partitions were pruned. Since475dbd0b7
, we now have knowledge of pruned partitions, we can do a much better job inside partitions_are_ordered(). Here we pass which partitions survived partition pruning into partitions_are_ordered() and, for LIST partitioning, have it check to see if any live partitions exist that are also in the new "interleaved_parts" field defined in PartitionBoundInfo. For RANGE partitioning we can relax the code which caused the partitions to be unordered if a DEFAULT partition existed. Since we now know which partitions were pruned, partitions_are_ordered() now returns true when the DEFAULT partition was pruned. Reviewed-by: Amit Langote, Zhihong Yu Discussion: https://postgr.es/m/CAApHDvrdoN_sXU52i=QDXe2k3WAo=EVry29r2+Tq2WYcn2xhEA@mail.gmail.com
This commit is contained in:
@ -61,6 +61,18 @@ struct RelOptInfo; /* avoid including pathnodes.h here */
|
||||
* The indexes array is indexed according to the hash key's remainder modulo
|
||||
* the greatest modulus, and it contains either the partition index accepting
|
||||
* that remainder, or -1 if there is no partition for that remainder.
|
||||
*
|
||||
* For LIST partitioned tables, we track the partition indexes of partitions
|
||||
* which are possibly "interleaved" partitions. A partition is considered
|
||||
* interleaved if it allows multiple values and there exists at least one
|
||||
* other partition which could contain a value that lies between those values.
|
||||
* For example, if a partition exists FOR VALUES IN(3,5) and another partition
|
||||
* exists FOR VALUES IN (4), then the IN(3,5) partition is an interleaved
|
||||
* partition. The same is possible with DEFAULT partitions since they can
|
||||
* contain any value that does not belong in another partition. This field
|
||||
* only serves as proof that a particular partition is not interleaved, not
|
||||
* proof that it is interleaved. When we're uncertain, we marked the
|
||||
* partition as interleaved.
|
||||
*/
|
||||
typedef struct PartitionBoundInfoData
|
||||
{
|
||||
@ -70,6 +82,9 @@ typedef struct PartitionBoundInfoData
|
||||
PartitionRangeDatumKind **kind; /* The kind of each range bound datum;
|
||||
* NULL for hash and list partitioned
|
||||
* tables */
|
||||
Bitmapset *interleaved_parts; /* Partition indexes of partitions which
|
||||
* may be interleaved. See above. This is
|
||||
* only set for LIST partitioned tables */
|
||||
int nindexes; /* Length of the indexes[] array */
|
||||
int *indexes; /* Partition indexes */
|
||||
int null_index; /* Index of the null-accepting partition; -1
|
||||
@ -102,7 +117,8 @@ extern PartitionBoundInfo partition_bounds_merge(int partnatts,
|
||||
JoinType jointype,
|
||||
List **outer_parts,
|
||||
List **inner_parts);
|
||||
extern bool partitions_are_ordered(PartitionBoundInfo boundinfo, int nparts);
|
||||
extern bool partitions_are_ordered(PartitionBoundInfo boundinfo,
|
||||
Bitmapset *live_parts);
|
||||
extern void check_new_partition_bound(char *relname, Relation parent,
|
||||
PartitionBoundSpec *spec,
|
||||
ParseState *pstate);
|
||||
|
Reference in New Issue
Block a user