summaryrefslogtreecommitdiff
path: root/src/backend/partitioning
diff options
context:
space:
mode:
authorTom Lane2019-03-30 22:58:55 +0000
committerTom Lane2019-03-30 22:58:55 +0000
commit428b260f87e8861ba8e58807b69d433db491c4f4 (patch)
tree19291c1fbbbd8cd3186b3789728ed7120a96a624 /src/backend/partitioning
parentad3107b97324e0c8cf65932294115b6af9db8ded (diff)
Speed up planning when partitions can be pruned at plan time.
Previously, the planner created RangeTblEntry and RelOptInfo structs for every partition of a partitioned table, even though many of them might later be deemed uninteresting thanks to partition pruning logic. This incurred significant overhead when there are many partitions. Arrange to postpone creation of these data structures until after we've processed the query enough to identify restriction quals for the partitioned table, and then apply partition pruning before not after creation of each partition's data structures. In this way we need not open the partition relations at all for partitions that the planner has no real interest in. For queries that can be proven at plan time to access only a small number of partitions, this patch improves the practical maximum number of partitions from under 100 to perhaps a few thousand. Amit Langote, reviewed at various times by Dilip Kumar, Jesper Pedersen, Yoshikazu Imai, and David Rowley Discussion: https://postgr.es/m/9d7c5112-cb99-6a47-d3be-cf1ee6862a1d@lab.ntt.co.jp
Diffstat (limited to 'src/backend/partitioning')
-rw-r--r--src/backend/partitioning/partprune.c45
1 files changed, 24 insertions, 21 deletions
diff --git a/src/backend/partitioning/partprune.c b/src/backend/partitioning/partprune.c
index af3f91133ed..59f34f5cac7 100644
--- a/src/backend/partitioning/partprune.c
+++ b/src/backend/partitioning/partprune.c
@@ -45,6 +45,7 @@
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/appendinfo.h"
+#include "optimizer/cost.h"
#include "optimizer/optimizer.h"
#include "optimizer/pathnode.h"
#include "parser/parsetree.h"
@@ -474,18 +475,24 @@ make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel,
* is, not pruned already).
*/
subplan_map = (int *) palloc(nparts * sizeof(int));
+ memset(subplan_map, -1, nparts * sizeof(int));
subpart_map = (int *) palloc(nparts * sizeof(int));
- relid_map = (Oid *) palloc(nparts * sizeof(Oid));
+ memset(subpart_map, -1, nparts * sizeof(int));
+ relid_map = (Oid *) palloc0(nparts * sizeof(Oid));
present_parts = NULL;
for (i = 0; i < nparts; i++)
{
RelOptInfo *partrel = subpart->part_rels[i];
- int subplanidx = relid_subplan_map[partrel->relid] - 1;
- int subpartidx = relid_subpart_map[partrel->relid] - 1;
+ int subplanidx;
+ int subpartidx;
- subplan_map[i] = subplanidx;
- subpart_map[i] = subpartidx;
+ /* Skip processing pruned partitions. */
+ if (partrel == NULL)
+ continue;
+
+ subplan_map[i] = subplanidx = relid_subplan_map[partrel->relid] - 1;
+ subpart_map[i] = subpartidx = relid_subpart_map[partrel->relid] - 1;
relid_map[i] = planner_rt_fetch(partrel->relid, root)->relid;
if (subplanidx >= 0)
{
@@ -567,23 +574,20 @@ gen_partprune_steps(RelOptInfo *rel, List *clauses, bool *contradictory)
/*
* prune_append_rel_partitions
- * Returns RT indexes of the minimum set of child partitions which must
- * be scanned to satisfy rel's baserestrictinfo quals.
+ * Returns indexes into rel->part_rels of the minimum set of child
+ * partitions which must be scanned to satisfy rel's baserestrictinfo
+ * quals.
*
* Callers must ensure that 'rel' is a partitioned table.
*/
-Relids
+Bitmapset *
prune_append_rel_partitions(RelOptInfo *rel)
{
- Relids result;
List *clauses = rel->baserestrictinfo;
List *pruning_steps;
bool contradictory;
PartitionPruneContext context;
- Bitmapset *partindexes;
- int i;
- Assert(clauses != NIL);
Assert(rel->part_scheme != NULL);
/* If there are no partitions, return the empty set */
@@ -591,6 +595,13 @@ prune_append_rel_partitions(RelOptInfo *rel)
return NULL;
/*
+ * If pruning is disabled or if there are no clauses to prune with, return
+ * all partitions.
+ */
+ if (!enable_partition_pruning || clauses == NIL)
+ return bms_add_range(NULL, 0, rel->nparts - 1);
+
+ /*
* Process clauses. If the clauses are found to be contradictory, we can
* return the empty set.
*/
@@ -617,15 +628,7 @@ prune_append_rel_partitions(RelOptInfo *rel)
context.evalexecparams = false;
/* Actual pruning happens here. */
- partindexes = get_matching_partitions(&context, pruning_steps);
-
- /* Add selected partitions' RT indexes to result. */
- i = -1;
- result = NULL;
- while ((i = bms_next_member(partindexes, i)) >= 0)
- result = bms_add_member(result, rel->part_rels[i]->relid);
-
- return result;
+ return get_matching_partitions(&context, pruning_steps);
}
/*