mirror of
https://github.com/postgres/postgres.git
synced 2025-10-27 00:12:01 +03:00
Use parameterized paths to generate inner indexscans more flexibly.
This patch fixes the planner so that it can generate nestloop-with- inner-indexscan plans even with one or more levels of joining between the indexscan and the nestloop join that is supplying the parameter. The executor was fixed to handle such cases some time ago, but the planner was not ready. This should improve our plans in many situations where join ordering restrictions formerly forced complete table scans. There is probably a fair amount of tuning work yet to be done, because of various heuristics that have been added to limit the number of parameterized paths considered. However, we are not going to find out what needs to be adjusted until the code gets some real-world use, so it's time to get it in there where it can be tested easily. Note API change for index AM amcostestimate functions. I'm not aware of any non-core index AMs, but if there are any, they will need minor adjustments.
This commit is contained in:
@@ -68,9 +68,9 @@ extern double index_pages_fetched(double tuples_fetched, BlockNumber pages,
|
||||
double index_pages, PlannerInfo *root);
|
||||
extern void cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel);
|
||||
extern void cost_index(IndexPath *path, PlannerInfo *root,
|
||||
RelOptInfo *outer_rel);
|
||||
double loop_count);
|
||||
extern void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
|
||||
Path *bitmapqual, RelOptInfo *outer_rel);
|
||||
Path *bitmapqual, double loop_count);
|
||||
extern void cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root);
|
||||
extern void cost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root);
|
||||
extern void cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec);
|
||||
@@ -107,15 +107,47 @@ extern void cost_group(Path *path, PlannerInfo *root,
|
||||
int numGroupCols, double numGroups,
|
||||
Cost input_startup_cost, Cost input_total_cost,
|
||||
double input_tuples);
|
||||
extern void cost_nestloop(NestPath *path, PlannerInfo *root,
|
||||
SpecialJoinInfo *sjinfo);
|
||||
extern void cost_mergejoin(MergePath *path, PlannerInfo *root,
|
||||
SpecialJoinInfo *sjinfo);
|
||||
extern void cost_hashjoin(HashPath *path, PlannerInfo *root,
|
||||
SpecialJoinInfo *sjinfo);
|
||||
extern void initial_cost_nestloop(PlannerInfo *root,
|
||||
JoinCostWorkspace *workspace,
|
||||
JoinType jointype,
|
||||
Path *outer_path, Path *inner_path,
|
||||
SpecialJoinInfo *sjinfo,
|
||||
SemiAntiJoinFactors *semifactors);
|
||||
extern void final_cost_nestloop(PlannerInfo *root, NestPath *path,
|
||||
JoinCostWorkspace *workspace,
|
||||
SpecialJoinInfo *sjinfo,
|
||||
SemiAntiJoinFactors *semifactors);
|
||||
extern void initial_cost_mergejoin(PlannerInfo *root,
|
||||
JoinCostWorkspace *workspace,
|
||||
JoinType jointype,
|
||||
List *mergeclauses,
|
||||
Path *outer_path, Path *inner_path,
|
||||
List *outersortkeys, List *innersortkeys,
|
||||
SpecialJoinInfo *sjinfo);
|
||||
extern void final_cost_mergejoin(PlannerInfo *root, MergePath *path,
|
||||
JoinCostWorkspace *workspace,
|
||||
SpecialJoinInfo *sjinfo);
|
||||
extern void initial_cost_hashjoin(PlannerInfo *root,
|
||||
JoinCostWorkspace *workspace,
|
||||
JoinType jointype,
|
||||
List *hashclauses,
|
||||
Path *outer_path, Path *inner_path,
|
||||
SpecialJoinInfo *sjinfo,
|
||||
SemiAntiJoinFactors *semifactors);
|
||||
extern void final_cost_hashjoin(PlannerInfo *root, HashPath *path,
|
||||
JoinCostWorkspace *workspace,
|
||||
SpecialJoinInfo *sjinfo,
|
||||
SemiAntiJoinFactors *semifactors);
|
||||
extern void cost_subplan(PlannerInfo *root, SubPlan *subplan, Plan *plan);
|
||||
extern void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root);
|
||||
extern void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root);
|
||||
extern void compute_semi_anti_join_factors(PlannerInfo *root,
|
||||
RelOptInfo *outerrel,
|
||||
RelOptInfo *innerrel,
|
||||
JoinType jointype,
|
||||
SpecialJoinInfo *sjinfo,
|
||||
List *restrictlist,
|
||||
SemiAntiJoinFactors *semifactors);
|
||||
extern void set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel);
|
||||
extern void set_joinrel_size_estimates(PlannerInfo *root, RelOptInfo *rel,
|
||||
RelOptInfo *outer_rel,
|
||||
|
||||
@@ -26,6 +26,9 @@ extern int compare_fractional_path_costs(Path *path1, Path *path2,
|
||||
double fraction);
|
||||
extern void set_cheapest(RelOptInfo *parent_rel);
|
||||
extern void add_path(RelOptInfo *parent_rel, Path *new_path);
|
||||
extern bool add_path_precheck(RelOptInfo *parent_rel,
|
||||
Cost startup_cost, Cost total_cost,
|
||||
List *pathkeys, Relids required_outer);
|
||||
|
||||
extern Path *create_seqscan_path(PlannerInfo *root, RelOptInfo *rel);
|
||||
extern IndexPath *create_index_path(PlannerInfo *root,
|
||||
@@ -37,11 +40,12 @@ extern IndexPath *create_index_path(PlannerInfo *root,
|
||||
List *pathkeys,
|
||||
ScanDirection indexscandir,
|
||||
bool indexonly,
|
||||
RelOptInfo *outer_rel);
|
||||
Relids required_outer,
|
||||
double loop_count);
|
||||
extern BitmapHeapPath *create_bitmap_heap_path(PlannerInfo *root,
|
||||
RelOptInfo *rel,
|
||||
Path *bitmapqual,
|
||||
RelOptInfo *outer_rel);
|
||||
double loop_count);
|
||||
extern BitmapAndPath *create_bitmap_and_path(PlannerInfo *root,
|
||||
RelOptInfo *rel,
|
||||
List *bitmapquals);
|
||||
@@ -66,23 +70,31 @@ extern Path *create_ctescan_path(PlannerInfo *root, RelOptInfo *rel);
|
||||
extern Path *create_worktablescan_path(PlannerInfo *root, RelOptInfo *rel);
|
||||
extern ForeignPath *create_foreignscan_path(PlannerInfo *root, RelOptInfo *rel);
|
||||
|
||||
extern Relids calc_nestloop_required_outer(Path *outer_path, Path *inner_path);
|
||||
extern Relids calc_non_nestloop_required_outer(Path *outer_path, Path *inner_path);
|
||||
|
||||
extern NestPath *create_nestloop_path(PlannerInfo *root,
|
||||
RelOptInfo *joinrel,
|
||||
JoinType jointype,
|
||||
JoinCostWorkspace *workspace,
|
||||
SpecialJoinInfo *sjinfo,
|
||||
SemiAntiJoinFactors *semifactors,
|
||||
Path *outer_path,
|
||||
Path *inner_path,
|
||||
List *restrict_clauses,
|
||||
List *pathkeys);
|
||||
List *pathkeys,
|
||||
Relids required_outer);
|
||||
|
||||
extern MergePath *create_mergejoin_path(PlannerInfo *root,
|
||||
RelOptInfo *joinrel,
|
||||
JoinType jointype,
|
||||
JoinCostWorkspace *workspace,
|
||||
SpecialJoinInfo *sjinfo,
|
||||
Path *outer_path,
|
||||
Path *inner_path,
|
||||
List *restrict_clauses,
|
||||
List *pathkeys,
|
||||
Relids required_outer,
|
||||
List *mergeclauses,
|
||||
List *outersortkeys,
|
||||
List *innersortkeys);
|
||||
@@ -90,10 +102,13 @@ extern MergePath *create_mergejoin_path(PlannerInfo *root,
|
||||
extern HashPath *create_hashjoin_path(PlannerInfo *root,
|
||||
RelOptInfo *joinrel,
|
||||
JoinType jointype,
|
||||
JoinCostWorkspace *workspace,
|
||||
SpecialJoinInfo *sjinfo,
|
||||
SemiAntiJoinFactors *semifactors,
|
||||
Path *outer_path,
|
||||
Path *inner_path,
|
||||
List *restrict_clauses,
|
||||
Relids required_outer,
|
||||
List *hashclauses);
|
||||
|
||||
/*
|
||||
|
||||
@@ -44,17 +44,14 @@ extern void debug_print_rel(PlannerInfo *root, RelOptInfo *rel);
|
||||
*/
|
||||
extern void create_index_paths(PlannerInfo *root, RelOptInfo *rel);
|
||||
extern List *generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
|
||||
List *clauses, List *outer_clauses,
|
||||
RelOptInfo *outer_rel);
|
||||
extern void best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
|
||||
RelOptInfo *outer_rel, JoinType jointype,
|
||||
Path **cheapest_startup, Path **cheapest_total);
|
||||
List *clauses, List *other_clauses,
|
||||
bool restriction_only);
|
||||
extern bool relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
|
||||
List *restrictlist,
|
||||
List *exprlist, List *oprlist);
|
||||
extern bool eclass_matches_any_index(EquivalenceClass *ec,
|
||||
EquivalenceMember *em,
|
||||
RelOptInfo *rel);
|
||||
extern bool eclass_member_matches_indexcol(EquivalenceClass *ec,
|
||||
EquivalenceMember *em,
|
||||
IndexOptInfo *index, int indexcol);
|
||||
extern bool match_index_to_operand(Node *operand, int indexcol,
|
||||
IndexOptInfo *index);
|
||||
extern void expand_indexqual_conditions(IndexOptInfo *index,
|
||||
@@ -127,9 +124,9 @@ extern void add_child_rel_equivalences(PlannerInfo *root,
|
||||
extern void mutate_eclass_expressions(PlannerInfo *root,
|
||||
Node *(*mutator) (),
|
||||
void *context);
|
||||
extern List *find_eclass_clauses_for_index_join(PlannerInfo *root,
|
||||
RelOptInfo *rel,
|
||||
Relids outer_relids);
|
||||
extern List *generate_implied_equalities_for_indexcol(PlannerInfo *root,
|
||||
IndexOptInfo *index,
|
||||
int indexcol);
|
||||
extern bool have_relevant_eclass_joinclause(PlannerInfo *root,
|
||||
RelOptInfo *rel1, RelOptInfo *rel2);
|
||||
extern bool has_relevant_eclass_joinclause(PlannerInfo *root,
|
||||
@@ -153,9 +150,11 @@ extern List *canonicalize_pathkeys(PlannerInfo *root, List *pathkeys);
|
||||
extern PathKeysComparison compare_pathkeys(List *keys1, List *keys2);
|
||||
extern bool pathkeys_contained_in(List *keys1, List *keys2);
|
||||
extern Path *get_cheapest_path_for_pathkeys(List *paths, List *pathkeys,
|
||||
Relids required_outer,
|
||||
CostSelector cost_criterion);
|
||||
extern Path *get_cheapest_fractional_path_for_pathkeys(List *paths,
|
||||
List *pathkeys,
|
||||
Relids required_outer,
|
||||
double fraction);
|
||||
extern List *build_index_pathkeys(PlannerInfo *root, IndexOptInfo *index,
|
||||
ScanDirection scandir);
|
||||
|
||||
@@ -40,8 +40,7 @@ extern List *extract_actual_clauses(List *restrictinfo_list,
|
||||
extern void extract_actual_join_clauses(List *restrictinfo_list,
|
||||
List **joinquals,
|
||||
List **otherquals);
|
||||
extern List *select_nonredundant_join_clauses(PlannerInfo *root,
|
||||
List *restrictinfo_list,
|
||||
Path *inner_path);
|
||||
extern List *select_nonredundant_join_clauses(List *restrictinfo_list,
|
||||
List *reference_list);
|
||||
|
||||
#endif /* RESTRICTINFO_H */
|
||||
|
||||
Reference in New Issue
Block a user