Changeset: 94db23a8d2ea for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=94db23a8d2ea
Modified Files:
        sql/server/rel_dump.c
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimizer.c
        sql/server/rel_rel.c
        sql/server/rel_rel.h
        sql/server/rel_select.c
        sql/server/rel_unnest.c
        sql/server/rel_updates.c
Branch: Jun2020
Log Message:

Performance fix for tcpds q80 and related.

1. Fixed handling of cardinality of atomic expressions through groupings.
2. Added rel_setop_set_exps call which sets the cardinality of expressions 
under a set relation, which was missing.
3. Updated exp_reset_card_and_freevar for these cases.


diffs (truncated from 428 to 300 lines):

diff --git a/sql/server/rel_dump.c b/sql/server/rel_dump.c
--- a/sql/server/rel_dump.c
+++ b/sql/server/rel_dump.c
@@ -1803,7 +1803,7 @@ rel_read(mvc *sql, char *r, int *pos, li
                if (!(exps = read_exps(sql, NULL, NULL, NULL, r, pos, '[', 0)))
                        return NULL;
                rel = rel_setop(sql->sa, lrel, rrel, j);
-               rel->exps = exps;
+               rel_setop_set_exps(sql, rel, exps);
                if (rel_set_types(sql, rel) < 0)
                        return sql_error(sql, -1, SQLSTATE(42000) "Setop: 
number of expressions don't match\n");
                set_processed(rel);
diff --git a/sql/server/rel_exp.c b/sql/server/rel_exp.c
--- a/sql/server/rel_exp.c
+++ b/sql/server/rel_exp.c
@@ -675,16 +675,16 @@ exp_alias_or_copy( mvc *sql, const char 
                tname = exp_relname(old);
 
        if (!cname && exp_name(old) && has_label(old)) {
-               ne = exp_column(sql->sa, exp_relname(old), exp_name(old), 
exp_subtype(old), orel?orel->card:CARD_ATOM, has_nil(old), is_intern(old));
+               ne = exp_column(sql->sa, exp_relname(old), exp_name(old), 
exp_subtype(old), orel && old->card != CARD_ATOM?orel->card:CARD_ATOM, 
has_nil(old), is_intern(old));
                return exp_propagate(sql->sa, ne, old);
        } else if (!cname) {
                exp_label(sql->sa, old, ++sql->label);
-               ne = exp_column(sql->sa, exp_relname(old), exp_name(old), 
exp_subtype(old), orel?orel->card:CARD_ATOM, has_nil(old), is_intern(old));
+               ne = exp_column(sql->sa, exp_relname(old), exp_name(old), 
exp_subtype(old), orel && old->card != CARD_ATOM?orel->card:CARD_ATOM, 
has_nil(old), is_intern(old));
                return exp_propagate(sql->sa, ne, old);
        } else if (cname && !old->alias.name) {
                exp_setname(sql->sa, old, tname, cname);
        }
-       ne = exp_column(sql->sa, tname, cname, exp_subtype(old), 
orel?orel->card:CARD_ATOM, has_nil(old), is_intern(old));
+       ne = exp_column(sql->sa, tname, cname, exp_subtype(old), orel && 
old->card != CARD_ATOM?orel->card:CARD_ATOM, has_nil(old), is_intern(old));
        return exp_propagate(sql->sa, ne, old);
 }
 
@@ -1574,7 +1574,7 @@ rel_find_exp_and_corresponding_rel_( sql
 }
 
 sql_exp *
-rel_find_exp_and_corresponding_rel(sql_rel *rel, sql_exp *e, sql_rel **res)
+rel_find_exp_and_corresponding_rel(sql_rel *rel, sql_exp *e, sql_rel **res, 
bool *under_join)
 {
        sql_exp *ne = rel_find_exp_and_corresponding_rel_(rel, e, res);
 
@@ -1584,9 +1584,11 @@ rel_find_exp_and_corresponding_rel(sql_r
                case op_right:
                case op_full:
                case op_join:
-                       ne = rel_find_exp_and_corresponding_rel(rel->l, e, res);
+                       ne = rel_find_exp_and_corresponding_rel(rel->l, e, res, 
under_join);
                        if (!ne)
-                               ne = rel_find_exp_and_corresponding_rel(rel->r, 
e, res);
+                               ne = rel_find_exp_and_corresponding_rel(rel->r, 
e, res, under_join);
+                       if (ne && under_join)
+                               *under_join = true;
                        break;
                case op_table:
                        if (rel->exps && e->type == e_column && e->l && 
exps_bind_column2(rel->exps, e->l, e->r))
@@ -1599,7 +1601,7 @@ rel_find_exp_and_corresponding_rel(sql_r
                case op_inter:
                {
                        if (rel->l)
-                               ne = rel_find_exp_and_corresponding_rel(rel->l, 
e, res);
+                               ne = rel_find_exp_and_corresponding_rel(rel->l, 
e, res, under_join);
                        else if (rel->exps && e->l) {
                                ne = exps_bind_column2(rel->exps, e->l, e->r);
                                if (ne && res)
@@ -1619,7 +1621,9 @@ rel_find_exp_and_corresponding_rel(sql_r
                        break;
                default:
                        if (!is_project(rel->op) && rel->l)
-                               ne = rel_find_exp_and_corresponding_rel(rel->l, 
e, res);
+                               ne = rel_find_exp_and_corresponding_rel(rel->l, 
e, res, under_join);
+                       if (ne && (rel->op == op_semi || rel->op == op_anti) && 
under_join)
+                               *under_join = true;
                }
        }
        return ne;
@@ -1628,7 +1632,7 @@ rel_find_exp_and_corresponding_rel(sql_r
 sql_exp *
 rel_find_exp( sql_rel *rel, sql_exp *e)
 {
-       return rel_find_exp_and_corresponding_rel(rel, e, NULL);
+       return rel_find_exp_and_corresponding_rel(rel, e, NULL, NULL);
 }
 
 int
diff --git a/sql/server/rel_exp.h b/sql/server/rel_exp.h
--- a/sql/server/rel_exp.h
+++ b/sql/server/rel_exp.h
@@ -125,7 +125,7 @@ extern unsigned int exp_card(sql_exp *e)
 extern const char *exp_find_rel_name(sql_exp *e);
 
 extern sql_exp *rel_find_exp( sql_rel *rel, sql_exp *e);
-extern sql_exp *rel_find_exp_and_corresponding_rel(sql_rel *rel, sql_exp *e, 
sql_rel **res);
+extern sql_exp *rel_find_exp_and_corresponding_rel(sql_rel *rel, sql_exp *e, 
sql_rel **res, bool *under_join);
 
 extern int exp_cmp( sql_exp *e1, sql_exp *e2);
 extern int exp_equal( sql_exp *e1, sql_exp *e2);
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
@@ -4191,8 +4191,7 @@ rel_push_aggr_down(mvc *sql, sql_rel *re
                }
 
                u = rel_setop(sql->sa, ul, ur, op_union);
-               u->exps = rel_projections(sql, ul, NULL, 1, 1);
-               u->nrcols = list_length(u->exps);
+               rel_setop_set_exps(sql, u, rel_projections(sql, ul, NULL, 1, 
1));
                set_processed(u);
 
                if (rel->r) {
@@ -4709,12 +4708,13 @@ find_simple_projection_for_join2semi(sql
                if (e->type == e_column) {
                        sql_rel *res = NULL;
                        sql_exp *found = NULL;
+                       bool underjoin = false;
 
                        if (is_groupby(rel->op) || need_distinct(rel) || 
find_prop(e->p, PROP_HASHCOL))
                                return true;
 
-                       found = rel_find_exp_and_corresponding_rel(rel->l, e, 
&res); /* grouping column on inner relation */
-                       if (found) {
+                       found = rel_find_exp_and_corresponding_rel(rel->l, e, 
&res, &underjoin); /* grouping column on inner relation */
+                       if (found && !underjoin) {
                                if (find_prop(found->p, PROP_HASHCOL)) /* 
primary key always unique */
                                        return true;
                                if (found->type == e_column && found->card <= 
CARD_AGGR) {
@@ -5589,6 +5589,8 @@ score_gbe(mvc *sql, sql_rel *rel, sql_ex
        sql_subtype *t = exp_subtype(e);
        sql_column *c = NULL;
 
+       if (e->card == CARD_ATOM) /* constants are trivial to group */
+               res += 1000;
        /* can we find out if the underlying table is sorted */
        if ((c = exp_find_column(rel, e, -2)) && mvc_is_sorted(sql, c))
                res += 600;
@@ -8525,8 +8527,7 @@ rel_split_outerjoin(mvc *sql, sql_rel *r
                        add_nulls( sql, nr, r);
                        exps = rel_projections(sql, nl, NULL, 1, 1);
                        nl = rel_setop(sql->sa, nl, nr, op_union);
-                       nl->exps = exps;
-                       nr->nrcols = list_length(exps);
+                       rel_setop_set_exps(sql, nl, exps);
                        set_processed(nl);
                }
                if (rel->op == op_right || rel->op == op_full) {
@@ -8545,8 +8546,7 @@ rel_split_outerjoin(mvc *sql, sql_rel *r
                                (fdup)NULL);
                        exps = rel_projections(sql, nl, NULL, 1, 1);
                        nl = rel_setop(sql->sa, nl, nr, op_union);
-                       nl->exps = exps;
-                       nl->nrcols = list_length(exps);
+                       rel_setop_set_exps(sql, nl, exps);
                        set_processed(nl);
                }
 
@@ -8949,7 +8949,7 @@ rel_merge_table_rewrite(mvc *sql, sql_re
                                                        sql_rel *l = n->data;
                                                        sql_rel *r = 
n->next->data;
                                                        nrel = 
rel_setop(sql->sa, l, r, op_union);
-                                                       rel_set_exps(nrel, 
rel_projections(sql, rel, NULL, 1, 1));
+                                                       rel_setop_set_exps(sql, 
nrel, rel_projections(sql, rel, NULL, 1, 1));
                                                        set_processed(nrel);
                                                        append(ntables, nrel);
                                                }
diff --git a/sql/server/rel_rel.c b/sql/server/rel_rel.c
--- a/sql/server/rel_rel.c
+++ b/sql/server/rel_rel.c
@@ -484,15 +484,9 @@ rel_setop(sql_allocator *sa, sql_rel *l,
        rel->r = r;
        rel->op = setop;
        rel->exps = NULL;
-       if (setop == op_union) {
-               rel->card = CARD_MULTI;
-       } else {
-               rel->card = l->card;
-       }
-       if (l && r) {
-               assert(l->nrcols == r->nrcols);
-               rel->nrcols = l->nrcols;
-       }
+       rel->card = is_union(setop) ? CARD_MULTI : l->card;
+       assert(l->nrcols == r->nrcols);
+       rel->nrcols = l->nrcols;
        return rel;
 }
 
@@ -522,6 +516,28 @@ rel_setop_check_types(mvc *sql, sql_rel 
        return rel_setop(sql->sa, l, r, op);
 }
 
+void
+rel_setop_set_exps(mvc *sql, sql_rel *rel, list *exps)
+{
+       sql_rel *l = rel->l, *r = rel->r;
+       list *lexps = l->exps, *rexps = r->exps;
+
+       if (!is_project(l->op))
+               lexps = rel_projections(sql, l, NULL, 0, 1);
+       if (!is_project(r->op))
+               rexps = rel_projections(sql, r, NULL, 0, 1);
+
+       assert(is_set(rel->op) && list_length(lexps) == list_length(rexps) && 
list_length(exps) == list_length(lexps));
+
+       for (node *n = exps->h, *m = lexps->h, *o = rexps->h ; m && m && o ; n 
= n->next, m = m->next,o = o->next) {
+               sql_exp *e = n->data, *f = m->data, *g = o->data;
+
+               e->card = is_union(rel->op) ? MAX(f->card, g->card) : f->card;
+       }
+       rel->nrcols = l->nrcols;
+       rel->exps = exps;
+}
+
 sql_rel *
 rel_crossproduct(sql_allocator *sa, sql_rel *l, sql_rel *r, operator_type join)
 {
@@ -922,7 +938,7 @@ rel_groupby(mvc *sql, sql_rel *l, list *
                        sql_exp *e = en->data, *ne;
 
                        /* after the group by the cardinality reduces */
-                       e->card = rel->card;
+                       e->card = MIN(e->card, rel->card); /* if the column is 
an atom, the cardinality should not change */
                        ne = exp_ref(sql, e);
                        ne = exp_propagate(sql->sa, ne, e);
                        append(aggrs, ne);
diff --git a/sql/server/rel_rel.h b/sql/server/rel_rel.h
--- a/sql/server/rel_rel.h
+++ b/sql/server/rel_rel.h
@@ -75,6 +75,7 @@ extern sql_rel *rel_inplace_groupby(sql_
 extern int rel_convert_types(mvc *sql, sql_rel *ll, sql_rel *rr, sql_exp **L, 
sql_exp **R, int scale_fixing, check_type tpe);
 extern sql_rel *rel_setop(sql_allocator *sa, sql_rel *l, sql_rel *r, 
operator_type setop);
 extern sql_rel *rel_setop_check_types(mvc *sql, sql_rel *l, sql_rel *r, list 
*ls, list *rs, operator_type op);
+extern void rel_setop_set_exps(mvc *sql, sql_rel *rel, list *exps);
 extern sql_rel *rel_crossproduct(sql_allocator *sa, sql_rel *l, sql_rel *r, 
operator_type join);
 
 /* in case e is an constant and rel is a simple project of only e, free rel */
diff --git a/sql/server/rel_select.c b/sql/server/rel_select.c
--- a/sql/server/rel_select.c
+++ b/sql/server/rel_select.c
@@ -5773,8 +5773,7 @@ rel_setquery_(sql_query *query, sql_rel 
                rel = rel_setop(sql->sa, l, r, (operator_type)op);
        }
        if (rel) {
-               rel->exps = rel_projections(sql, rel, NULL, 0, 1);
-               rel->nrcols = list_length(rel->exps);
+               rel_setop_set_exps(sql, rel, rel_projections(sql, rel, NULL, 0, 
1));
                set_processed(rel);
        }
        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
@@ -1630,16 +1630,6 @@ exp_reset_card_and_freevar(mvc *sql, sql
                return e;
 
        switch(rel->op){
-       case op_basetable:
-       case op_truncate:
-       case op_topn:
-       case op_sample:
-       case op_insert:
-       case op_update:
-       case op_delete:
-       case op_ddl:
-       case op_table:
-               break;
        case op_select:
        case op_join:
        case op_left:
@@ -1657,22 +1647,20 @@ exp_reset_card_and_freevar(mvc *sql, sql
                        e->card = exps_card(e->l);
                } break;
                case e_column: {
-                       sql_rel *l = rel->l, *r = rel->r, *ll = NULL, *rr = 
NULL;
                        sql_exp *le = NULL, *re = NULL;
-
-                       if (is_set(rel->op)) {
-                               le = rel_find_exp_and_corresponding_rel(l, e, 
&ll);
-                               re = rel_find_exp_and_corresponding_rel(r, e, 
&rr);
-                               if (ll && rr) /* TODO fix this? */
-                                       e->card = MAX(ll->card, rr->card);
-                       } else {
-                               if (l && (le = 
rel_find_exp_and_corresponding_rel(l, e, &ll)) && ll) {
-                                       e->card = ll->card;
-                               } else if (!is_simple_project(rel->op) && r && 
(re = rel_find_exp_and_corresponding_rel(r, e, &rr)) && rr) {
-                                       e->card = rr->card;
-                               }
+                       bool underjoinl = false, underjoinr = false;
+
+                       le = rel_find_exp_and_corresponding_rel(rel->l, e, 
NULL, &underjoinl);
+                       if (!is_simple_project(rel->op) && !is_inter(rel->op) 
&& !is_except(rel->op) && !is_semi(rel->op) && rel->r) {
+                               re = rel_find_exp_and_corresponding_rel(rel->r, 
e, NULL, &underjoinr);
+                               /* if the expression is found under a join, the 
cardinality expands to multi */
+                               e->card = 
MAX(le?underjoinl?CARD_MULTI:le->card:CARD_ATOM, 
re?underjoinr?CARD_MULTI:re->card:CARD_ATOM);
+                       } else if (e->card == CARD_ATOM) { /* unnested columns 
vs atoms */
+                               e->card = 
le?underjoinl?CARD_MULTI:le->card:CARD_ATOM;
+                       } else { /* general case */
+                               e->card = (le && 
!underjoinl)?le->card:CARD_MULTI;
                        }
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to