diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 051a854..38c27b7 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -4037,21 +4037,57 @@ void set_baserel_size_estimates(PlannerInfo *root, RelOptInfo *rel) { double nrows; + Selectivity prev_sel, sel; + List *clause_list; + List *ordered_clauses; + ListCell *l; + QualCost cost; /* Should only be applied to base relations */ Assert(rel->relid > 0); - nrows = rel->tuples * - clauselist_selectivity(root, - rel->baserestrictinfo, - 0, - JOIN_INNER, - NULL); + ordered_clauses = order_qual_clauses(root, rel->baserestrictinfo); + clause_list = ordered_clauses; - rel->rows = clamp_row_est(nrows); + cost.startup = 0; + cost.per_tuple = 0; + prev_sel = 1.0; + foreach(l, clause_list) + { + Node *qual = (Node *) lfirst(l); + List *clause_list_for_sel = NULL; + ListCell *m; + cost_qual_eval_context context; + context.root = root; + context.total.startup = 0; + context.total.per_tuple = 0; + + /* Make a temporary clause list for selectivity calcuation */ + foreach(m, ordered_clauses) + { + clause_list_for_sel = lappend(clause_list_for_sel, lfirst(m)); - cost_qual_eval(&rel->baserestrictcost, rel->baserestrictinfo, root); + if(m == l) + break; + } + + sel = clauselist_selectivity(root, + clause_list_for_sel, + 0, + JOIN_INNER, + NULL); + + cost_qual_eval_walker(qual, &context); + cost.startup += context.total.startup * prev_sel; + cost.per_tuple += context.total.per_tuple * prev_sel; + prev_sel = sel; + } + + nrows = rel->tuples * prev_sel; + + rel->rows = clamp_row_est(nrows); + rel->baserestrictcost = cost; set_rel_width(root, rel); } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 2821662..35d9755 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -159,7 +159,6 @@ static List *fix_indexqual_references(PlannerInfo *root, IndexPath *index_path); static List *fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path); static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol); static List *get_switched_clauses(List *clauses, Relids outerrelids); -static List *order_qual_clauses(PlannerInfo *root, List *clauses); static void copy_generic_path_info(Plan *dest, Path *src); static void copy_plan_costsize(Plan *dest, Plan *src); static void label_sort_with_costsize(PlannerInfo *root, Sort *plan, @@ -4762,7 +4761,7 @@ get_switched_clauses(List *clauses, Relids outerrelids) * instead of bare clauses. This is another reason why trying to consider * selectivity in the ordering would likely do the wrong thing. */ -static List * +List * order_qual_clauses(PlannerInfo *root, List *clauses) { typedef struct diff --git a/src/include/optimizer/planmain.h b/src/include/optimizer/planmain.h index f1d16cf..016fb12 100644 --- a/src/include/optimizer/planmain.h +++ b/src/include/optimizer/planmain.h @@ -64,6 +64,8 @@ extern Agg *make_agg(List *tlist, List *qual, List *groupingSets, List *chain, double dNumGroups, Plan *lefttree); extern Limit *make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount); +extern List *order_qual_clauses(PlannerInfo *root, List *clauses); + /* * prototypes for plan/initsplan.c