Changeset: aac6159ee0db for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=aac6159ee0db Modified Files: sql/backends/monet5/rel_bin.c sql/server/rel_optimizer.c sql/server/rel_unnest.c Branch: Jun2020 Log Message:
Added rewrite_split_select_exps rewriter, which splits selects expressions in two levels: simple expressions (ie no freevars or subrelations) to the bottom select and others to the top select. After unnesting, simple selections will remain on the bottom, thus there will be no need to push down these expressions again. This fixes a performance issue on tpcds q41. Also extended rel_push_topn_and_sample_down optimizer to merge nested topN relations with no offsets. Also fixed on rel2bin_semijoin without expressions, where the projection of the right relation would be ignored, thus leaving to wrong results. diffs (110 lines): diff --git a/sql/backends/monet5/rel_bin.c b/sql/backends/monet5/rel_bin.c --- a/sql/backends/monet5/rel_bin.c +++ b/sql/backends/monet5/rel_bin.c @@ -2635,6 +2635,7 @@ rel2bin_semijoin(backend *be, sql_rel *r join = stmt_join(be, l, r, 0, cmp_all, 0, false); } } else { + right = subrel_project(be, right, refs, rel->r); stmt *l = bin_first_column(be, left); stmt *r = bin_first_column(be, right); join = stmt_join(be, l, r, 0, cmp_all, 0, false); 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 @@ -2082,6 +2082,31 @@ rel_push_topn_and_sample_down(mvc *sql, 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 without offset */ + if (r && is_topn(rel->op) && is_topn(r->op) && list_length(rel->exps) == 1 && list_length(r->exps) == 1) { + sql_exp *topN1 = rel->exps->h->data, *topN2 = r->exps->h->data; + + if (topN1->l && topN2->l) { + atom *a1 = (atom *)topN1->l, *a2 = (atom *)topN2->l; + + if (a1->tpe.type->localtype == a2->tpe.type->localtype && !a1->isnull && !a2->isnull) { + if (atom_cmp(a1, a2) < 0) { + rel->l = r->l; + r->l = NULL; + rel_destroy(r); + (*changes)++; + return rel; + } else { + rel->l = NULL; + rel_destroy(rel); + rel = r; + (*changes)++; + return rel; + } + } + } + } + if (r && is_simple_project(r->op) && need_distinct(r)) return rel; 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 @@ -1819,6 +1819,51 @@ rewrite_or_exp(mvc *sql, sql_rel *rel, i return rel; } +static sql_rel * +rewrite_split_select_exps(mvc *sql, sql_rel *rel, int *changes) +{ + if (is_select(rel->op) && !list_empty(rel->exps)) { + int i = 0; + bool has_complex_exps = false, has_simple_exps = false, *complex_exps = (bool*) GDKmalloc(list_length(rel->exps) * sizeof(bool)); + + if (!complex_exps) + return sql_error(sql, 02, SQLSTATE(HY013) MAL_MALLOC_FAIL); + + for (node *n = rel->exps->h ; n ; n = n->next) { + sql_exp *e = n->data; + + if (exp_has_rel(e) || exp_has_freevar(sql, e)) { + complex_exps[i] = true; + has_complex_exps = true; + } else { + complex_exps[i] = false; + has_simple_exps = true; + } + i++; + } + + if (has_complex_exps && has_simple_exps) { + sql_rel *nsel = rel_select_copy(sql->sa, rel->l, NULL); + rel->l = nsel; + + i = 0; + for (node *n = rel->exps->h ; n ; ) { + node *nxt = n->next; + + if (!complex_exps[i]) { + rel_select_add_exp(sql->sa, nsel, n->data); + list_remove_node(rel->exps, n); + } + n = nxt; + i++; + } + (*changes)++; + } + GDKfree(complex_exps); + } + return rel; +} + /* exp visitor */ static sql_exp * rewrite_rank(mvc *sql, sql_rel *rel, sql_exp *e, int depth, int *changes) @@ -3028,6 +3073,8 @@ rel_unnest(mvc *sql, sql_rel *rel) rel = rel_visitor_bottomup(sql, rel, &rewrite_or_exp, &changes); if (changes > 0) rel = rel_visitor_bottomup(sql, rel, &rel_remove_empty_select, &changes); + rel = rel_visitor_bottomup(sql, rel, &rewrite_split_select_exps, &changes); /* has to run before rewrite_complex */ + rel = rel_visitor_bottomup(sql, rel, &rewrite_aggregates, &changes); rel = rel_exp_visitor_bottomup(sql, rel, &rewrite_rank, &changes); rel = rel_visitor_bottomup(sql, rel, &rewrite_outer2inner_union, &changes); _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list