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

Reply via email to