mirror of https://github.com/postgres/postgres
Add a new module backend/partitioning/partprune.c, implementing a more sophisticated algorithm for partition pruning. The new module uses each partition's "boundinfo" for pruning instead of constraint exclusion, based on an idea proposed by Robert Haas of a "pruning program": a list of steps generated from the query quals which are run iteratively to obtain a list of partitions that must be scanned in order to satisfy those quals. At present, this targets planner-time partition pruning, but there exist further patches to apply partition pruning at execution time as well. This commit also moves some definitions from include/catalog/partition.h to a new file include/partitioning/partbounds.h, in an attempt to rationalize partitioning related code. Authors: Amit Langote, David Rowley, Dilip Kumar Reviewers: Robert Haas, Kyotaro Horiguchi, Ashutosh Bapat, Jesper Pedersen. Discussion: https://postgr.es/m/098b9c71-1915-1a2a-8d52-1a7a50ce79e8@lab.ntt.co.jppull/27/merge
parent
11523e860f
commit
9fdb675fc5
@ -0,0 +1,17 @@ |
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile--
|
||||
# Makefile for backend/partitioning
|
||||
#
|
||||
# IDENTIFICATION
|
||||
# src/backend/partitioning/Makefile
|
||||
#
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
subdir = src/backend/partitioning
|
||||
top_builddir = ../../..
|
||||
include $(top_builddir)/src/Makefile.global |
||||
|
||||
OBJS = partprune.o
|
||||
|
||||
include $(top_srcdir)/src/backend/common.mk |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,124 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* partbounds.h |
||||
* |
||||
* Copyright (c) 2007-2018, PostgreSQL Global Development Group |
||||
* |
||||
* src/include/partitioning/partbounds.h |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef PARTBOUNDS_H |
||||
#define PARTBOUNDS_H |
||||
|
||||
#include "catalog/partition.h" |
||||
|
||||
|
||||
/*
|
||||
* PartitionBoundInfoData encapsulates a set of partition bounds. It is |
||||
* usually associated with partitioned tables as part of its partition |
||||
* descriptor, but may also be used to represent a virtual partitioned |
||||
* table such as a partitioned joinrel within the planner. |
||||
* |
||||
* A list partition datum that is known to be NULL is never put into the |
||||
* datums array. Instead, it is tracked using the null_index field. |
||||
* |
||||
* In the case of range partitioning, ndatums will typically be far less than |
||||
* 2 * nparts, because a partition's upper bound and the next partition's lower |
||||
* bound are the same in most common cases, and we only store one of them (the |
||||
* upper bound). In case of hash partitioning, ndatums will be same as the |
||||
* number of partitions. |
||||
* |
||||
* For range and list partitioned tables, datums is an array of datum-tuples |
||||
* with key->partnatts datums each. For hash partitioned tables, it is an array |
||||
* of datum-tuples with 2 datums, modulus and remainder, corresponding to a |
||||
* given partition. |
||||
* |
||||
* The datums in datums array are arranged in increasing order as defined by |
||||
* functions qsort_partition_rbound_cmp(), qsort_partition_list_value_cmp() and |
||||
* qsort_partition_hbound_cmp() for range, list and hash partitioned tables |
||||
* respectively. For range and list partitions this simply means that the |
||||
* datums in the datums array are arranged in increasing order as defined by |
||||
* the partition key's operator classes and collations. |
||||
* |
||||
* In the case of list partitioning, the indexes array stores one entry for |
||||
* every datum, which is the index of the partition that accepts a given datum. |
||||
* In case of range partitioning, it stores one entry per distinct range |
||||
* datum, which is the index of the partition for which a given datum |
||||
* is an upper bound. In the case of hash partitioning, the number of the |
||||
* entries in the indexes array is same as the greatest modulus amongst all |
||||
* partitions. For a given partition key datum-tuple, the index of the |
||||
* partition which would accept that datum-tuple would be given by the entry |
||||
* pointed by remainder produced when hash value of the datum-tuple is divided |
||||
* by the greatest modulus. |
||||
*/ |
||||
|
||||
typedef struct PartitionBoundInfoData |
||||
{ |
||||
char strategy; /* hash, list or range? */ |
||||
int ndatums; /* Length of the datums following array */ |
||||
Datum **datums; |
||||
PartitionRangeDatumKind **kind; /* The kind of each range bound datum;
|
||||
* NULL for hash and list partitioned |
||||
* tables */ |
||||
int *indexes; /* Partition indexes */ |
||||
int null_index; /* Index of the null-accepting partition; -1
|
||||
* if there isn't one */ |
||||
int default_index; /* Index of the default partition; -1 if there
|
||||
* isn't one */ |
||||
} PartitionBoundInfoData; |
||||
|
||||
#define partition_bound_accepts_nulls(bi) ((bi)->null_index != -1) |
||||
#define partition_bound_has_default(bi) ((bi)->default_index != -1) |
||||
|
||||
/*
|
||||
* When qsort'ing partition bounds after reading from the catalog, each bound |
||||
* is represented with one of the following structs. |
||||
*/ |
||||
|
||||
/* One bound of a hash partition */ |
||||
typedef struct PartitionHashBound |
||||
{ |
||||
int modulus; |
||||
int remainder; |
||||
int index; |
||||
} PartitionHashBound; |
||||
|
||||
/* One value coming from some (index'th) list partition */ |
||||
typedef struct PartitionListValue |
||||
{ |
||||
int index; |
||||
Datum value; |
||||
} PartitionListValue; |
||||
|
||||
/* One bound of a range partition */ |
||||
typedef struct PartitionRangeBound |
||||
{ |
||||
int index; |
||||
Datum *datums; /* range bound datums */ |
||||
PartitionRangeDatumKind *kind; /* the kind of each datum */ |
||||
bool lower; /* this is the lower (vs upper) bound */ |
||||
} PartitionRangeBound; |
||||
|
||||
extern int get_hash_partition_greatest_modulus(PartitionBoundInfo b); |
||||
extern int partition_list_bsearch(FmgrInfo *partsupfunc, Oid *partcollation, |
||||
PartitionBoundInfo boundinfo, |
||||
Datum value, bool *is_equal); |
||||
extern int partition_range_bsearch(int partnatts, FmgrInfo *partsupfunc, |
||||
Oid *partcollation, |
||||
PartitionBoundInfo boundinfo, |
||||
PartitionRangeBound *probe, bool *is_equal); |
||||
extern int partition_range_datum_bsearch(FmgrInfo *partsupfunc, |
||||
Oid *partcollation, |
||||
PartitionBoundInfo boundinfo, |
||||
int nvalues, Datum *values, bool *is_equal); |
||||
extern int partition_hash_bsearch(PartitionBoundInfo boundinfo, |
||||
int modulus, int remainder); |
||||
extern uint64 compute_hash_value(int partnatts, FmgrInfo *partsupfunc, |
||||
Datum *values, bool *isnull); |
||||
extern int32 partition_rbound_datum_cmp(FmgrInfo *partsupfunc, |
||||
Oid *partcollation, |
||||
Datum *rb_datums, PartitionRangeDatumKind *rb_kind, |
||||
Datum *tuple_datums, int n_tuple_datums); |
||||
|
||||
#endif /* PARTBOUNDS_H */ |
@ -0,0 +1,49 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* partprune.h |
||||
* prototypes for partprune.c |
||||
* |
||||
* |
||||
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* src/include/partitioning/partprune.h |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#ifndef PARTPRUNE_H |
||||
#define PARTPRUNE_H |
||||
|
||||
#include "catalog/partition.h" |
||||
#include "nodes/relation.h" |
||||
|
||||
/*
|
||||
* PartitionPruneContext |
||||
* |
||||
* Information about a partitioned table needed to perform partition pruning. |
||||
*/ |
||||
typedef struct PartitionPruneContext |
||||
{ |
||||
/* Partition key information */ |
||||
char strategy; |
||||
int partnatts; |
||||
Oid *partopfamily; |
||||
Oid *partopcintype; |
||||
Oid *partcollation; |
||||
FmgrInfo *partsupfunc; |
||||
|
||||
/* Number of partitions */ |
||||
int nparts; |
||||
|
||||
/* Partition boundary info */ |
||||
PartitionBoundInfo boundinfo; |
||||
} PartitionPruneContext; |
||||
|
||||
|
||||
extern Relids prune_append_rel_partitions(RelOptInfo *rel); |
||||
extern Bitmapset *get_matching_partitions(PartitionPruneContext *context, |
||||
List *pruning_steps); |
||||
extern List *gen_partprune_steps(RelOptInfo *rel, List *clauses, |
||||
bool *contradictory); |
||||
|
||||
#endif /* PARTPRUNE_H */ |
Loading…
Reference in new issue