Changeset: dedc75eaed76 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=dedc75eaed76
Modified Files:
sql/server/rel_optimizer.c
Branch: Jun2020
Log Message:
Revised rel_push_topn_and_sample_down optimizer. Avoid infinite optimization
loop by testing if a topN/sample relation already exists under the relation we
are trying to push under.
diffs (184 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
@@ -1957,18 +1957,20 @@ rel_simplify_fk_joins(visitor *v, sql_re
*/
static list *
-sum_limit_offset(mvc *sql, list *exps )
+sum_limit_offset(mvc *sql, sql_rel *rel)
{
list *nexps = new_exp_list(sql->sa);
sql_subtype *lng = sql_bind_localtype("lng");
sql_subfunc *add;
- /* if the expression list only consists of a limit expression,
- * we copy it */
- if (list_length(exps) == 1 && exps->h->data)
- return append(nexps, exps->h->data);
+ /* for sample we always propagate */
+ if (is_sample(rel->op))
+ return exps_copy(sql, rel->exps);
+ /* if the expression list only consists of a limit expression, we copy
it */
+ if (list_length(rel->exps) == 1 && rel->exps->h->data)
+ return append(nexps, rel->exps->h->data);
add = sql_bind_func_result(sql->sa, sql->session->schema, "sql_add",
F_FUNC, lng, 2, lng, lng);
- return append(nexps, exp_op(sql->sa, exps, add));
+ return append(nexps, exp_op(sql->sa, rel->exps, add));
}
static int
@@ -2050,11 +2052,9 @@ rel_rename_exps( mvc *sql, list *exps1,
static sql_rel *
rel_push_topn_and_sample_down(visitor *v, sql_rel *rel)
{
- sql_rel *rl, *r = rel->l;
+ sql_rel *rp = NULL, *r = rel->l;
if ((is_topn(rel->op) || is_sample(rel->op)) &&
topn_sample_save_exps(rel->exps)) {
- sql_rel *rp = NULL;
- operator_type relation_type = is_topn(rel->op) ? op_topn :
op_sample;
sql_rel *(*func) (sql_allocator *, sql_rel *, list *) =
is_topn(rel->op) ? rel_topn : rel_sample;
/* nested topN relations */
@@ -2101,11 +2101,10 @@ rel_push_topn_and_sample_down(visitor *v
}
}
- if (r && is_simple_project(r->op) && need_distinct(r))
+ if (r && need_distinct(r))
return rel;
/* push topn/sample under projections */
-
if (!rel_is_ref(rel) && r && is_simple_project(r->op) &&
!need_distinct(r) && !rel_is_ref(r) && r->l && !r->r) {
sql_rel *x = r, *px = x;
@@ -2113,7 +2112,10 @@ rel_push_topn_and_sample_down(visitor *v
px = x;
x = x->l;
}
-
+ /* only push topn once */
+ if (x && x->op == rel->op)
+ return rel;
+
rel->l = x;
px->l = rel;
rel = r;
@@ -2121,9 +2123,8 @@ rel_push_topn_and_sample_down(visitor *v
return rel;
}
- /* duplicate topn/sample direct under union */
-
- if (r && r->exps && is_union(r->op) && !rel_is_ref(r) && r->l) {
+ /* duplicate topn/sample direct under union or crossproduct */
+ if (r && !rel_is_ref(r) && r->l && r->r && ((is_union(r->op) &&
r->exps) || (r->op == op_join && list_empty(r->exps)))) {
sql_rel *u = r, *x;
sql_rel *ul = u->l;
sql_rel *ur = u->r;
@@ -2132,21 +2133,22 @@ rel_push_topn_and_sample_down(visitor *v
x = ul;
while (is_simple_project(x->op) && x->l)
x = x->l;
- if (x && x->op == relation_type)
+ if (x && x->op == rel->op)
return rel;
x = ur;
while (is_simple_project(x->op) && x->l)
x = x->l;
- if (x && x->op == relation_type)
+ if (x && x->op == rel->op)
return rel;
- ul = func(v->sql->sa, ul, sum_limit_offset(v->sql,
rel->exps));
- ur = func(v->sql->sa, ur, sum_limit_offset(v->sql,
rel->exps));
+ ul = func(v->sql->sa, ul, sum_limit_offset(v->sql,
rel));
+ ur = func(v->sql->sa, ur, sum_limit_offset(v->sql,
rel));
u->l = ul;
u->r = ur;
v->changes++;
return rel;
}
+
/* duplicate topn/sample + [ project-order ] under union */
if (r)
rp = r->l;
@@ -2160,12 +2162,12 @@ rel_push_topn_and_sample_down(visitor *v
x = ul;
while (is_simple_project(x->op) && x->l)
x = x->l;
- if (x && x->op == relation_type)
+ if (x && x->op == rel->op)
return rel;
x = ur;
while (is_simple_project(x->op) && x->l)
x = x->l;
- if (x && x->op == relation_type)
+ if (x && x->op == rel->op)
return rel;
if (list_length(ul->exps) > list_length(r->exps))
@@ -2189,7 +2191,7 @@ rel_push_topn_and_sample_down(visitor *v
ul->exps = list_merge(ul->exps,
exps_copy(v->sql, r->r), NULL);
ul->nrcols = list_length(ul->exps);
ul->r = exps_copy(v->sql, r->r);
- ul = func(v->sql->sa, ul, sum_limit_offset(v->sql,
rel->exps));
+ ul = func(v->sql->sa, ul, sum_limit_offset(v->sql,
rel));
ur = rel_project(v->sql->sa, ur, NULL);
ur->exps = exps_copy(v->sql, r->exps);
@@ -2198,7 +2200,7 @@ rel_push_topn_and_sample_down(visitor *v
ur->exps = list_merge(ur->exps,
exps_copy(v->sql, r->r), NULL);
ur->nrcols = list_length(ur->exps);
ur->r = exps_copy(v->sql, r->r);
- ur = func(v->sql->sa, ur, sum_limit_offset(v->sql,
rel->exps));
+ ur = func(v->sql->sa, ur, sum_limit_offset(v->sql,
rel));
u = rel_setop(v->sql->sa, ul, ur, op_union);
u->exps = exps_alias(v->sql, r->exps);
@@ -2228,29 +2230,6 @@ rel_push_topn_and_sample_down(visitor *v
v->changes++;
return rel;
}
-
- /* pass through projections */
- while (r && is_project(r->op) && !need_distinct(r) &&
- !rel_is_ref(r) &&
- !r->r && (rl = r->l) != NULL && is_project(rl->op)) {
- /* ensure there is no order by */
- if (!r->r) {
- r = r->l;
- } else {
- r = NULL;
- }
- }
- if (r && r != rel && is_simple_project(r->op) && !rel_is_ref(r)
&& !r->r && r->l)
- r = func(v->sql->sa, r, sum_limit_offset(v->sql,
rel->exps));
-
- /* push topn/sample under crossproduct */
- if (r && !r->exps && r->op == op_join && !rel_is_ref(r) &&
- ((sql_rel *)r->l)->op != relation_type && ((sql_rel
*)r->r)->op != relation_type) {
- r->l = func(v->sql->sa, r->l, sum_limit_offset(v->sql,
rel->exps));
- r->r = func(v->sql->sa, r->r, sum_limit_offset(v->sql,
rel->exps));
- v->changes++;
- return rel;
- }
/* TODO */
#if 0
/* duplicate topn/sample + [ project-order ] under join on
independend always matching joins */
@@ -2258,10 +2237,10 @@ rel_push_topn_and_sample_down(visitor *v
rp = r->l;
if (r && r->exps && is_simple_project(r->op) &&
!(rel_is_ref(r)) && r->r && r->l &&
rp->op == op_join && rp->exps && rp->exps->h &&
((prop*)((sql_exp*)rp->exps->h->data)->p)->kind == PROP_FETCH &&
- ((sql_rel *)rp->l)->op != relation_type && ((sql_rel
*)rp->r)->op != relation_type) {
+ ((sql_rel *)rp->l)->op != rel->op && ((sql_rel *)rp->r)->op
!= rel->op) {
/* TODO check if order by columns are independend of
join conditions */
- r->l = func(v->sql->sa, r->l, sum_limit_offset(v->sql,
rel->exps));
- r->r = func(v->sql->sa, r->r, sum_limit_offset(v->sql,
rel->exps));
+ r->l = func(v->sql->sa, r->l, sum_limit_offset(v->sql,
rel));
+ r->r = func(v->sql->sa, r->r, sum_limit_offset(v->sql,
rel));
v->changes++;
return rel;
}
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list