mirror of
https://github.com/postgres/postgres.git
synced 2025-08-28 18:48:04 +03:00
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
This commit is contained in:
@@ -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,29 +574,33 @@ 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 */
|
||||
if (rel->nparts == 0)
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user