Changeset: d3387ab7ba04 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=d3387ab7ba04 Modified Files: sql/server/rel_optimizer.c sql/server/rel_unnest.c Branch: default Log Message:
Packing semi and anti join optimizers diffs (218 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 @@ -1520,7 +1520,7 @@ rel_push_func_down(visitor *v, sql_rel * return rel; if (exps_can_push_func(exps, rel, &push_left, &push_right) && exps_need_push_down(exps)) { sql_rel *nrel, *ol = l, *or = r; - visitor nv = { .sql = v->sql, .parent = v->parent, .value_based_opt = v->value_based_opt, .storage_based_opt = v->storage_based_opt }; + visitor nv = { .sql = v->sql, .parent = v->parent, .value_based_opt = v->value_based_opt, .storage_based_opt = v->storage_based_opt, .data = v->data }; /* we need a full projection, group by's and unions cannot be extended * with more expressions */ @@ -4815,17 +4815,22 @@ rel_push_join_down(visitor *v, sql_rel * * * in some cases the other way is usefull, ie push join down * semijoin. When the join reduces (ie when there are selects on it). + * + * At the moment, we only flag changes by this optimizer on the first level of optimization */ -static sql_rel * +static inline sql_rel * rel_push_semijoin_down_or_up(visitor *v, sql_rel *rel) { + int level = *(int*)v->data; + if (rel->op == op_join && rel->exps && rel->l) { sql_rel *l = rel->l, *r = rel->r; if (is_semi(l->op) && !rel_is_ref(l) && is_select(r->op) && !rel_is_ref(r)) { rel->l = l->l; l->l = rel; - v->changes++; + if (level <= 0) + v->changes++; return l; } } @@ -4840,7 +4845,8 @@ rel_push_semijoin_down_or_up(visitor *v, if (is_semi(ll->op) && !rel_is_ref(ll)) { l->l = ll->l; ll->l = rel; - v->changes++; + if (level <= 0) + v->changes++; return ll; } } @@ -4859,7 +4865,8 @@ rel_push_semijoin_down_or_up(visitor *v, } rel_select_add_exp(v->sql->sa, rel->l, e); list_remove_node(rel->exps, NULL, n); - v->changes++; + if (level <= 0) + v->changes++; } n = next; } @@ -4927,7 +4934,8 @@ rel_push_semijoin_down_or_up(visitor *v, l->exps = njexps; rel_destroy(rel); rel = l; - v->changes++; + if (level <= 0) + v->changes++; } return rel; } @@ -8466,10 +8474,11 @@ is_identity_of(sql_exp *e, sql_rel *l) return 1; } -static sql_rel * +static inline sql_rel * rel_rewrite_semijoin(visitor *v, sql_rel *rel) { - if (is_semi(rel->op)) { + assert(is_semi(rel->op)); + { sql_rel *l = rel->l; sql_rel *r = rel->r; sql_rel *rl = (r->l)?r->l:NULL; @@ -8499,7 +8508,7 @@ rel_rewrite_semijoin(visitor *v, sql_rel v->changes++; } } - if (is_semi(rel->op)) { + { sql_rel *l = rel->l, *rl = NULL; sql_rel *r = rel->r, *or = r; @@ -8583,36 +8592,49 @@ rel_rewrite_semijoin(visitor *v, sql_rel } /* antijoin(a, union(b,c)) -> antijoin(antijoin(a,b), c) */ -static sql_rel * +static inline sql_rel * rel_rewrite_antijoin(visitor *v, sql_rel *rel) { - if (rel->op == op_anti) { - sql_rel *l = rel->l; - sql_rel *r = rel->r; - - if (l && !rel_is_ref(l) && - r && !rel_is_ref(r) && is_union(r->op) && !is_single(r)) { - sql_rel *rl = rel_dup(r->l), *nl; - sql_rel *rr = rel_dup(r->r); - - if (!is_project(rl->op)) - rl = rel_project(v->sql->sa, rl, - rel_projections(v->sql, rl, NULL, 1, 1)); - if (!is_project(rr->op)) - rr = rel_project(v->sql->sa, rr, - rel_projections(v->sql, rr, NULL, 1, 1)); - rel_rename_exps(v->sql, r->exps, rl->exps); - rel_rename_exps(v->sql, r->exps, rr->exps); - - nl = rel_crossproduct(v->sql->sa, rel->l, rl, op_anti); - nl->exps = exps_copy(v->sql, rel->exps); - rel->l = nl; - rel->r = rr; - rel_destroy(r); - v->changes++; - return rel; - } - } + sql_rel *l = rel->l; + sql_rel *r = rel->r; + + assert(rel->op == op_anti); + if (l && !rel_is_ref(l) && r && !rel_is_ref(r) && is_union(r->op) && !is_single(r)) { + sql_rel *rl = rel_dup(r->l), *nl; + sql_rel *rr = rel_dup(r->r); + + if (!is_project(rl->op)) + rl = rel_project(v->sql->sa, rl, + rel_projections(v->sql, rl, NULL, 1, 1)); + if (!is_project(rr->op)) + rr = rel_project(v->sql->sa, rr, + rel_projections(v->sql, rr, NULL, 1, 1)); + rel_rename_exps(v->sql, r->exps, rl->exps); + rel_rename_exps(v->sql, r->exps, rr->exps); + + nl = rel_crossproduct(v->sql->sa, rel->l, rl, op_anti); + nl->exps = exps_copy(v->sql, rel->exps); + rel->l = nl; + rel->r = rr; + rel_destroy(r); + v->changes++; + return rel; + } + return rel; +} + +static sql_rel * +rel_optimize_semi_and_anti(visitor *v, sql_rel *rel) +{ + /* rewrite semijoin (A, join(A,B)) into semijoin (A,B) */ + if (is_semi(rel->op)) + rel = rel_rewrite_semijoin(v, rel); + /* push semijoin through join */ + if (is_semi(rel->op) || is_innerjoin(rel->op)) + rel = rel_push_semijoin_down_or_up(v, rel); + /* antijoin(a, union(b,c)) -> antijoin(antijoin(a,b), c) */ + if (rel->op == op_anti) + rel = rel_rewrite_antijoin(v, rel); return rel; } @@ -9315,7 +9337,7 @@ rel_merge_table_rewrite(visitor *v, sql_ } rel_destroy(rel); if (sel) { - visitor iv = { .sql = v->sql, .value_based_opt = v->value_based_opt, .storage_based_opt = v->storage_based_opt }; + visitor iv = { .sql = v->sql, .value_based_opt = v->value_based_opt, .storage_based_opt = v->storage_based_opt, .data = v->data }; sel->l = nrel; sel = rel_visitor_topdown(&iv, sel, &rel_push_select_down_union); if (iv.changes) @@ -9605,8 +9627,7 @@ rel_remove_union_partitions(visitor *v, static sql_rel * optimize_rel(mvc *sql, sql_rel *rel, int *g_changes, int level, bool value_based_opt, bool storage_based_opt) { - visitor v = { .sql = sql, .value_based_opt = value_based_opt, .storage_based_opt = storage_based_opt }, - ev = { .sql = sql, .value_based_opt = value_based_opt, .storage_based_opt = storage_based_opt }; + visitor v = { .sql = sql, .value_based_opt = value_based_opt, .storage_based_opt = storage_based_opt, .data = &level }; global_props gp = (global_props) {.cnt = {0},}; rel_properties(sql, &gp, rel); @@ -9733,16 +9754,7 @@ optimize_rel(mvc *sql, sql_rel *rel, int } if (gp.cnt[op_anti] || gp.cnt[op_semi]) { - /* rewrite semijoin (A, join(A,B)) into semijoin (A,B) */ - rel = rel_visitor_bottomup(&v, rel, &rel_rewrite_semijoin); - /* push semijoin through join */ - ev.changes = 0; - rel = rel_visitor_bottomup(&ev, rel, &rel_push_semijoin_down_or_up); - if (level == 0) /* for now count optimizer changes just for first iteration */ - v.changes += ev.changes; - /* antijoin(a, union(b,c)) -> antijoin(antijoin(a,b), c) */ - if (gp.cnt[op_anti] && gp.cnt[op_union]) - rel = rel_visitor_bottomup(&v, rel, &rel_rewrite_antijoin); + rel = rel_visitor_bottomup(&v, rel, &rel_optimize_semi_and_anti); if (level <= 0) rel = rel_visitor_topdown(&v, rel, &rel_semijoin_use_fk); } diff --git a/sql/server/rel_unnest.c b/sql/server/rel_unnest.c --- a/sql/server/rel_unnest.c +++ b/sql/server/rel_unnest.c @@ -3565,7 +3565,8 @@ rewrite_values(visitor *v, sql_rel *rel) sql_rel * rel_unnest(mvc *sql, sql_rel *rel) { - visitor v = { .sql = sql }; + int level = 0; + visitor v = { .sql = sql, .data = &level }; /* make it compatible with rel_optimizer, so set the level to 0 */ rel = rel_exp_visitor_bottomup(&v, rel, &rewrite_simplify_exp, false); rel = rel_visitor_bottomup(&v, rel, &rewrite_simplify); _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list