diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 21 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepunion.c | 59 |
2 files changed, 64 insertions, 16 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 132e8a35a39..d7ff36d89be 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -2254,10 +2254,9 @@ set_dummy_rel_pathlist(RelOptInfo *rel) * return false. */ static bool -find_window_run_conditions(Query *subquery, RangeTblEntry *rte, - AttrNumber attno, WindowFunc *wfunc, OpExpr *opexpr, - bool wfunc_left, bool *keep_original, - Bitmapset **run_cond_attrs) +find_window_run_conditions(Query *subquery, AttrNumber attno, + WindowFunc *wfunc, OpExpr *opexpr, bool wfunc_left, + bool *keep_original, Bitmapset **run_cond_attrs) { Oid prosupport; Expr *otherexpr; @@ -2445,7 +2444,7 @@ find_window_run_conditions(Query *subquery, RangeTblEntry *rte, * will use the runCondition to stop returning tuples. */ static bool -check_and_push_window_quals(Query *subquery, RangeTblEntry *rte, Node *clause, +check_and_push_window_quals(Query *subquery, Node *clause, Bitmapset **run_cond_attrs) { OpExpr *opexpr = (OpExpr *) clause; @@ -2485,9 +2484,8 @@ check_and_push_window_quals(Query *subquery, RangeTblEntry *rte, Node *clause, TargetEntry *tle = list_nth(subquery->targetList, var1->varattno - 1); WindowFunc *wfunc = (WindowFunc *) tle->expr; - if (find_window_run_conditions(subquery, rte, tle->resno, wfunc, - opexpr, true, &keep_original, - run_cond_attrs)) + if (find_window_run_conditions(subquery, tle->resno, wfunc, opexpr, + true, &keep_original, run_cond_attrs)) return keep_original; } @@ -2498,9 +2496,8 @@ check_and_push_window_quals(Query *subquery, RangeTblEntry *rte, Node *clause, TargetEntry *tle = list_nth(subquery->targetList, var2->varattno - 1); WindowFunc *wfunc = (WindowFunc *) tle->expr; - if (find_window_run_conditions(subquery, rte, tle->resno, wfunc, - opexpr, false, &keep_original, - run_cond_attrs)) + if (find_window_run_conditions(subquery, tle->resno, wfunc, opexpr, + false, &keep_original, run_cond_attrs)) return keep_original; } @@ -2622,7 +2619,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel, * runCondition. */ if (!subquery->hasWindowFuncs || - check_and_push_window_quals(subquery, rte, clause, + check_and_push_window_quals(subquery, clause, &run_cond_attrs)) { /* diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 28a4ae64440..6bd0f4a5dc3 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -23,6 +23,8 @@ */ #include "postgres.h" +#include <math.h> + #include "access/htup_details.h" #include "catalog/pg_type.h" #include "miscadmin.h" @@ -74,6 +76,8 @@ static List *generate_append_tlist(List *colTypes, List *colCollations, List *input_tlists, List *refnames_tlist); static List *generate_setop_grouplist(SetOperationStmt *op, List *targetlist); +static PathTarget *create_setop_pathtarget(PlannerInfo *root, List *tlist, + List *child_pathlist); /* @@ -803,7 +807,8 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, /* Build result relation. */ result_rel = fetch_upper_rel(root, UPPERREL_SETOP, relids); - result_rel->reltarget = create_pathtarget(root, tlist); + result_rel->reltarget = create_setop_pathtarget(root, tlist, + cheapest_pathlist); result_rel->consider_parallel = consider_parallel; result_rel->consider_startup = (root->tuple_fraction > 0); @@ -892,7 +897,7 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, path = (Path *) create_agg_path(root, result_rel, apath, - create_pathtarget(root, tlist), + result_rel->reltarget, AGG_HASHED, AGGSPLIT_SIMPLE, groupList, @@ -908,7 +913,7 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root, path = (Path *) create_agg_path(root, result_rel, gpath, - create_pathtarget(root, tlist), + result_rel->reltarget, AGG_HASHED, AGGSPLIT_SIMPLE, groupList, @@ -1130,7 +1135,18 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root, /* Build result relation. */ result_rel = fetch_upper_rel(root, UPPERREL_SETOP, bms_union(lrel->relids, rrel->relids)); - result_rel->reltarget = create_pathtarget(root, tlist); + + /* + * Create the PathTarget and set the width accordingly. For EXCEPT, since + * the set op result won't contain rows from the rpath, we only account + * for the width of the lpath. For INTERSECT, use both input paths. + */ + if (op->op == SETOP_EXCEPT) + result_rel->reltarget = create_setop_pathtarget(root, tlist, + list_make1(lpath)); + else + result_rel->reltarget = create_setop_pathtarget(root, tlist, + list_make2(lpath, rpath)); /* * Estimate number of distinct groups that we'll need hashtable entries @@ -1619,3 +1635,38 @@ generate_setop_grouplist(SetOperationStmt *op, List *targetlist) Assert(lg == NULL); return grouplist; } + +/* + * create_setop_pathtarget + * Do the normal create_pathtarget() work, plus set the resulting + * PathTarget's width to the average width of the Paths in child_pathlist + * weighted using the estimated row count of each path. + * + * Note: This is required because set op target lists use varno==0, which + * results in a type default width estimate rather than one that's based on + * statistics of the columns from the set op children. + */ +static PathTarget * +create_setop_pathtarget(PlannerInfo *root, List *tlist, List *child_pathlist) +{ + PathTarget *reltarget; + ListCell *lc; + double parent_rows = 0; + double parent_size = 0; + + reltarget = create_pathtarget(root, tlist); + + /* Calculate the total rows and total size. */ + foreach(lc, child_pathlist) + { + Path *path = (Path *) lfirst(lc); + + parent_rows += path->rows; + parent_size += path->parent->reltarget->width * path->rows; + } + + if (parent_rows > 0) + reltarget->width = rint(parent_size / parent_rows); + + return reltarget; +} |