Changeset: bbd8d70e4268 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=bbd8d70e4268 Modified Files: sql/server/rel_optimizer.c Branch: Nov2019 Log Message:
Perform rel_push_semijoin_down and rel_push_join_down optimizers after rel_join_order, so semijoins will be always pushed bellow regular joins diffs (183 lines): diff --git a/sql/server/rel_optimizer.c b/sql/server/rel_optimizer.c --- a/sql/server/rel_optimizer.c +++ b/sql/server/rel_optimizer.c @@ -1374,7 +1374,7 @@ static sql_exp * if (get_cmp(e) == cmp_or || get_cmp(e) == cmp_filter) { list *l, *r; - l = exps_push_down(sql, e->l, f, t); + l = exps_push_down(sql, e->l, f, t); if (!l) return NULL; r = exps_push_down(sql, e->r, f, t); @@ -1448,7 +1448,6 @@ exp_push_down(mvc *sql, sql_exp *e, sql_ return _exp_push_down(sql, e, f, t); } - /* some projections results are order dependend (row_number etc) */ static int project_unsafe(sql_rel *rel, int allow_identity) @@ -1760,13 +1759,13 @@ rel_push_count_down(int *changes, mvc *s if (!is_groupby(rel->op)) return rel; - r = rel->l; + r = rel->l; if (is_groupby(rel->op) && !rel_is_ref(rel) && - r && !r->exps && r->op == op_join && !(rel_is_ref(r)) && - /* currently only single count aggregation is handled, no other projects or aggregation */ - list_length(rel->exps) == 1 && exp_aggr_is_count(rel->exps->h->data)) { - sql_exp *nce, *oce; + r && !r->exps && r->op == op_join && !(rel_is_ref(r)) && + /* currently only single count aggregation is handled, no other projects or aggregation */ + list_length(rel->exps) == 1 && exp_aggr_is_count(rel->exps->h->data)) { + sql_exp *nce, *oce; sql_rel *gbl, *gbr; /* Group By */ sql_rel *cp; /* Cross Product */ sql_subfunc *mult; @@ -1780,7 +1779,7 @@ rel_push_count_down(int *changes, mvc *s rname = exp_relname(oce); name = exp_name(oce); - args = new_exp_list(sql->sa); + args = new_exp_list(sql->sa); srel = r->l; { sql_subaggr *cf = sql_bind_aggr(sql->sa, sql->session->schema, "count", NULL); @@ -6069,7 +6068,7 @@ exps_remove_dictexps(mvc *sql, list *exp static sql_rel * rel_remove_join(int *changes, mvc *sql, sql_rel *rel) { - if (is_join(rel->op) && !is_outerjoin(rel->op) && /* DISABLES CODE */ (0)) { + if (is_join(rel->op) && !is_outerjoin(rel->op)) { sql_rel *l = rel->l; sql_rel *r = rel->r; int lconst = 0, rconst = 0; @@ -6100,7 +6099,7 @@ rel_remove_join(int *changes, mvc *sql, list_merge(rel->exps, r->exps, (fdup)NULL); } } - if (is_join(rel->op) && /* DISABLES CODE */ (0)) { + if (is_join(rel->op)) { sql_rel *l = rel->l; sql_rel *r = rel->r; int ldict = 0, rdict = 0; @@ -6137,7 +6136,7 @@ rel_remove_join(int *changes, mvc *sql, * where non of the project_cols are from B and x=y is a foreign key join (B is the unique side) * and there are no filters on B */ - if (/* DISABLES CODE */ (0) && is_project(rel->op)) { + if (is_project(rel->op)) { sql_rel *j = rel->l; if (is_join(j->op)) { @@ -8354,7 +8353,7 @@ add_nulls(mvc *sql, sql_rel *rel, sql_re static sql_rel * rel_split_outerjoin(int *changes, mvc *sql, sql_rel *rel) { - if (/* DISABLES CODE */ (0) && (rel->op == op_left || rel->op == op_right || rel->op == op_full) && + if ((rel->op == op_left || rel->op == op_right || rel->op == op_full) && list_length(rel->exps) == 1 && exps_nr_of_or(rel->exps) == list_length(rel->exps)) { sql_rel *l = rel->l, *nl, *nll, *nlr; sql_rel *r = rel->r, *nr; @@ -9153,13 +9152,13 @@ optimize_rel(mvc *sql, sql_rel *rel, int * also joins between a relation and a DICT (which isn't used) * could be removed. * */ - if (gp.cnt[op_join] && gp.cnt[op_project]) + if (gp.cnt[op_join] && gp.cnt[op_project] && /* DISABLES CODE */ (0)) rel = rewrite(sql, rel, &rel_remove_join, &changes); if (gp.cnt[op_join] || - gp.cnt[op_left] || gp.cnt[op_right] || gp.cnt[op_full] || - gp.cnt[op_semi] || gp.cnt[op_anti] || - gp.cnt[op_select]) { + gp.cnt[op_left] || gp.cnt[op_right] || gp.cnt[op_full] || + gp.cnt[op_semi] || gp.cnt[op_anti] || + gp.cnt[op_select]) { rel = rewrite(sql, rel, &rel_find_range, &changes); if (value_based_opt) { rel = rel_project_reduce_casts(&changes, sql, rel); @@ -9179,38 +9178,15 @@ optimize_rel(mvc *sql, sql_rel *rel, int rel = rewrite(sql, rel, &rel_rewrite_types, &changes); - if (gp.cnt[op_anti] || gp.cnt[op_semi]) { - /* rewrite semijoin (A, join(A,B)) into semijoin (A,B) */ - rel = rewrite(sql, rel, &rel_rewrite_semijoin, &changes); - /* push semijoin through join */ - rel = rewrite(sql, rel, &rel_push_semijoin_down, &changes); - /* antijoin(a, union(b,c)) -> antijoin(antijoin(a,b), c) */ - rel = rewrite(sql, rel, &rel_rewrite_antijoin, &changes); - if (level <= 0) - rel = rewrite_topdown(sql, rel, &rel_semijoin_use_fk, &changes); - } - - if (gp.cnt[op_left] || gp.cnt[op_right] || gp.cnt[op_full]) + if ((gp.cnt[op_left] || gp.cnt[op_right] || gp.cnt[op_full]) && /* DISABLES CODE */ (0)) rel = rewrite_topdown(sql, rel, &rel_split_outerjoin, &changes); if (gp.cnt[op_select] || gp.cnt[op_project]) if (level == 1) /* only once */ rel = rewrite(sql, rel, &rel_merge_rse, &changes); - if (gp.cnt[op_select] && gp.cnt[op_join]) { - if (/* DISABLES CODE */ (0)) rel = rewrite_topdown(sql, rel, &rel_push_select_down_join, &changes); - rel = rewrite(sql, rel, &rel_remove_empty_select, &e_changes); - } - - if (gp.cnt[op_join] && gp.cnt[op_groupby]) { - rel = rewrite_topdown(sql, rel, &rel_push_count_down, &changes); - if (level <= 0) - rel = rewrite_topdown(sql, rel, &rel_push_join_down, &changes); - - /* push_join_down introduces semijoins */ - /* rewrite semijoin (A, join(A,B)) into semijoin (A,B) */ - rel = rewrite(sql, rel, &rel_rewrite_semijoin, &changes); - } + if (gp.cnt[op_select] && gp.cnt[op_join] && /* DISABLES CODE */ (0)) + rel = rewrite_topdown(sql, rel, &rel_push_select_down_join, &changes); if (gp.cnt[op_select]) rel = rewrite_topdown(sql, rel, &rel_push_select_down_union, &changes); @@ -9218,6 +9194,9 @@ optimize_rel(mvc *sql, sql_rel *rel, int if (gp.cnt[op_union] && gp.cnt[op_select]) rel = rewrite(sql, rel, &rel_remove_union_partitions, &changes); + if (gp.cnt[op_select]) + rel = rewrite(sql, rel, &rel_remove_empty_select, &e_changes); + if (gp.cnt[op_groupby]) { rel = rewrite_topdown(sql, rel, &rel_push_aggr_down, &changes); rel = rewrite_topdown(sql, rel, &rel_push_groupby_down, &changes); @@ -9240,6 +9219,28 @@ optimize_rel(mvc *sql, sql_rel *rel, int rel = rewrite(sql, rel, &rel_merge_identical_joins, &e_changes); } + /* Important -> Re-write semijoins after rel_join_order */ + if ((gp.cnt[op_join] || gp.cnt[op_semi] || gp.cnt[op_anti]) && gp.cnt[op_groupby]) { + rel = rewrite_topdown(sql, rel, &rel_push_count_down, &changes); + if (level <= 0) + rel = rewrite_topdown(sql, rel, &rel_push_join_down, &changes); + + /* push_join_down introduces semijoins */ + /* rewrite semijoin (A, join(A,B)) into semijoin (A,B) */ + rel = rewrite(sql, rel, &rel_rewrite_semijoin, &changes); + } + + if (gp.cnt[op_anti] || gp.cnt[op_semi]) { + /* rewrite semijoin (A, join(A,B)) into semijoin (A,B) */ + rel = rewrite(sql, rel, &rel_rewrite_semijoin, &changes); + /* push semijoin through join */ + rel = rewrite(sql, rel, &rel_push_semijoin_down, &changes); + /* antijoin(a, union(b,c)) -> antijoin(antijoin(a,b), c) */ + rel = rewrite(sql, rel, &rel_rewrite_antijoin, &changes); + if (level <= 0) + rel = rewrite_topdown(sql, rel, &rel_semijoin_use_fk, &changes); + } + /* Important -> Make sure rel_push_select_down gets called after rel_join_order, because pushing down select expressions makes rel_join_order more difficult */ if (gp.cnt[op_select] || gp.cnt[op_semi]) { _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list