Changeset: 00fb7a4501c0 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/00fb7a4501c0
Modified Files:
        monetdb5/modules/mal/pp_hash.c
        sql/backends/monet5/rel_pphash.c
        sql/rel.txt
        sql/server/rel_dump.c
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimize_proj.c
        sql/server/rel_optimize_sel.c
        sql/server/rel_optimizer.c
        sql/server/rel_optimizer_private.h
        sql/server/rel_prop.c
        sql/server/rel_prop.h
        sql/server/rel_statistics.c
        sql/server/rel_statistics.h
        sql/server/rel_unnest.c
Branch: pp_hashjoin
Log Message:

add join reorders based on selectivity and cost calculation for pipelines


diffs (truncated from 2387 to 300 lines):

diff --git a/monetdb5/modules/mal/pp_hash.c b/monetdb5/modules/mal/pp_hash.c
--- a/monetdb5/modules/mal/pp_hash.c
+++ b/monetdb5/modules/mal/pp_hash.c
@@ -1144,7 +1144,7 @@ error:
                                        if (slots == 0) { \
                                                slots = ht_preclaim(private); \
                                                slot = ATOMIC_ADD(&h->last, 
slots); \
-                                               if (((slot*100)/100) >= 
(gid)h->size) { \
+                                               if (((slot*100)/70) >= 
(gid)h->size) { \
                                                        hash_rehash(h, p, err); 
\
                                                        vals = h->vals; \
                                                        pgids = h->pgids; \
@@ -1192,7 +1192,7 @@ error:
                                                if (slots == 0) { \
                                                        slots = 
ht_preclaim(private); \
                                                        slot = 
ATOMIC_ADD(&h->last, slots); \
-                                                       if (((slot*100)/100) >= 
(gid)h->size) { \
+                                                       if (((slot*100)/70) >= 
(gid)h->size) { \
                                                                hash_rehash(h, 
p, err); \
                                                                vals = h->vals; 
\
                                                                pgids = 
h->pgids; \
diff --git a/sql/backends/monet5/rel_pphash.c b/sql/backends/monet5/rel_pphash.c
--- a/sql/backends/monet5/rel_pphash.c
+++ b/sql/backends/monet5/rel_pphash.c
@@ -295,7 +295,7 @@ rel2bin_oahash_build(backend *be, sql_re
        bool need_freq = (rel->flag != (int)op_semi || rel->ref.refcnt > 2 || 
!list_empty(exps_prj_hsh));
        if (need_freq && list_length(exps_cmp_hsh) == 1 && !is_single(rel)) {
                sql_exp *e = exps_cmp_hsh->h->data;
-               if (e->unique)
+               if (0 && e->unique)
                        need_freq = false;
        }
        lng bld_sz = _estimate(be->mvc, rel); /* TODO: change into dynamic 
where possible ?? */
diff --git a/sql/rel.txt b/sql/rel.txt
--- a/sql/rel.txt
+++ b/sql/rel.txt
@@ -99,15 +99,15 @@ INSERT|DELETE|UPDATE|TRUNCATE       (card ATO
 
        -> flag         (if set don't insert (is done already))
 only (UPDATE)
-       -> exps         
-                       UPDATE: Named columns to update 
+       -> exps
+                       UPDATE: Named columns to update
                        DELETE: deleted rows (for returning return all columns 
(the deleted content))
                        INSERT: inserted values
                        TRUNCATE: The first expression is a e_atom integer 
indicating to restart sequences, and the second is another e_atom integer 
telling to cascade the truncate if the table has fk dependents
-       -> attr         UPDATE: for returning all columns of updated rows       
        
+       -> attr         UPDATE: for returning all columns of updated rows
 
 TODO cleanup
-UPDATE have a special case     
+UPDATE have a special case
 
                        for inserts/updates with indices a double
                        relation is used as we need to keep access to
@@ -121,7 +121,7 @@ PROBEHASH
        -> attr         hash-expressions
        -> exps         payload
 
-PARTITION      
+PARTITION
        -> l            relation
        -> attr         hash-expressions
        -> exps         payload
@@ -144,15 +144,15 @@ e_convert
 e_cmp
        -> l    left sub expression
        -> r    right sub expression (f second arg (->f) for range expressions)
-       -> flag compare type            
+       -> flag compare type
                (
-                       cmp_gt = 0,             or [ v > l && v < h ] 
+                       cmp_gt = 0,             or [ v > l && v < h ]
                        cmp_gte = 1,            or [ v >= l && v < h ]
                        cmp_lte = 2,            or [ v > l && v <= h ]
                        cmp_lt = 3,             or [ v >= l && v <= h ]
-                                                uses flag&CMP_BETWEEN bit for 
handling nil 
+                                                uses flag&CMP_BETWEEN bit for 
handling nil
                                                        open ranges and isNull 
vs NULL
-                                                uses flag&CMP_SYMMETRIC bit 
for symmetric 
+                                                uses flag&CMP_SYMMETRIC bit 
for symmetric
                        cmp_equal = 4,
                        cmp_notequal = 5,
 
@@ -191,9 +191,11 @@ e_column
        -> rname alias for the relation (i.e., alias of ->l, used by higher 
expressions)
        -> name alias for the expression (i.e., alias of ->r, used by higher 
expressions)
                l,r names of referred expression
-       -> l    optional relation name 
+       -> l    optional relation name
        -> r    expression name
-       -> type 
+       -> f    pointer to relation, if expression is part of base table
+       -> nid == label of referenced expression (down the tree)
+       -> type
 
 e_psm
        -> flag
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
@@ -386,7 +386,7 @@ exp_print(mvc *sql, stream *fout, sql_ex
                /* don't show properties on value lists */
                if (decorate && e->p && e->type != e_atom && !exp_is_atom(e)) {
                        for (prop *p = e->p; p; p = p->p) {
-                               if (p->kind != PROP_MIN && p->kind != PROP_MAX 
&& p->kind != PROP_NUNIQUES) {
+                               if (p->kind != PROP_MIN && p->kind != PROP_MAX 
&& p->kind != PROP_NUNIQUES && p->kind != PROP_SELECTIVITY) {
                                        char *pv = propvalue2string(ta, p);
                                        mnstr_printf(fout, " %s %s", 
propkind2string(p), pv);
                                }
@@ -776,7 +776,7 @@ rel_print_rel(mvc *sql, stream  *fout, s
                if ((ATOMIC_GET(&GDKdebug) & TESTINGMASK) == 0 && 
rel->partition)
                                mnstr_printf(fout, " %c PARTITION", 
rel->partition==1?'L':rel->partition == 2?'R':' ');
                for (prop *p = rel->p; p; p = p->p) {
-                       if ((p->kind != PROP_COUNT && p->kind != PROP_UKEY && 
p->kind != PROP_UNNESTING) || (ATOMIC_GET(&GDKdebug) & TESTINGMASK) == 0) {
+                       if ((p->kind != PROP_COUNT && p->kind != PROP_UKEY && 
p->kind != PROP_UNNESTING && p->kind != PROP_SELECTIVITY) || 
(ATOMIC_GET(&GDKdebug) & TESTINGMASK) == 0) {
                                char *pv = propvalue2string(ta, p);
                                mnstr_printf(fout, " %s %s", 
propkind2string(p), pv);
                        }
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
@@ -1473,7 +1473,11 @@ exp_match_exp_semantics( sql_exp *e1, sq
        if (e1->type == e2->type) {
                switch(e1->type) {
                case e_cmp:
-                       if (e1->flag == e2->flag && !is_complex_exp(e1->flag) &&
+                       if (e1->flag == e2->flag && e1->flag == cmp_equal && 
!is_anti(e1) && !is_anti(e2) &&
+                           ((exp_match_exp(e1->l, e2->l) && 
exp_match_exp(e1->r, e2->r)) ||
+                           (exp_match_exp(e1->l, e2->r) && 
exp_match_exp(e1->r, e2->l))))
+                               return 1;
+                       else if (e1->flag == e2->flag && 
!is_complex_exp(e1->flag) &&
                            exp_match_exp(e1->l, e2->l) && exp_match_exp(e1->r, 
e2->r) &&
                            ((!e1->f && !e2->f) || (e1->f && e2->f && 
exp_match_exp(e1->f, e2->f))))
                                return 1;
@@ -1539,6 +1543,12 @@ exp_match_exp( sql_exp *e1, sql_exp *e2)
        return exp_match_exp_semantics( e1, e2, true);
 }
 
+int
+exp_match_exp_cmp( sql_exp *e1, sql_exp *e2)
+{
+       return !exp_match_exp_semantics( e1, e2, true);
+}
+
 sql_exp *
 exps_any_match(list *l, sql_exp *e)
 {
@@ -4324,6 +4334,137 @@ free_exp(allocator *sa, sql_exp *e)
        _free_exp_internal(sa, e);
 }
 
+dbl
+exp_estimate_selectivity(mvc *sql, sql_exp *e)
+{
+       dbl sel = 0.1;
+       (void)sql;
+       if (!e)
+               return 1.0;
+       switch (e->type) {
+       case e_atom:
+               if (exp_is_true(e))
+                       return 1.0;
+               if (exp_is_false(e))
+                       return 0.0;
+               return 0.5;
+       case e_column:
+               return 0.1;
+       case e_convert:
+               return exp_estimate_selectivity(sql, (sql_exp *) e->l);
+       case e_func:
+               return 0.1;
+       case e_aggr:
+               return 0.1;
+       case e_cmp: {
+               sql_exp *l = (sql_exp *) e->l, *r = (sql_exp *) e->r;
+               if (e->flag <= cmp_lte && e->f) {
+                       sel = 0.50;
+               } else {
+                       switch (e->flag) {
+                       case cmp_equal:
+                               if (exp_is_atom(r) && !exp_is_atom(l)) {
+                                       prop *p = find_prop(l->p, 
PROP_NUNIQUES);
+                                       if (p && p->value.dval > 1)
+                                               sel = 1.0 / p->value.dval;
+                                       else
+                                               sel = 0.1;
+                               } else if (exp_is_atom(l) && !exp_is_atom(r)) {
+                                       prop *p = find_prop(r->p, 
PROP_NUNIQUES);
+                                       if (p && p->value.dval > 1)
+                                               sel = 1.0 / p->value.dval;
+                                       else
+                                               sel = 0.1;
+                               } else if (!exp_is_atom(l) && !exp_is_atom(r)) {
+                                       prop *pl = find_prop(l->p, 
PROP_NUNIQUES), *pr = find_prop(r->p, PROP_NUNIQUES);
+                                       if (pl && pr && pl->value.dval > 0 && 
pr->value.dval > 0)
+                                               sel = 1.0 / MAX(pl->value.dval, 
pr->value.dval);
+                                       else if (pl && pl->value.dval > 0)
+                                               sel = 1.0 / pl->value.dval;
+                                       else if (pr && pr->value.dval > 0)
+                                               sel = 1.0 / pr->value.dval;
+                                       else
+                                               sel = 0.1;
+                               } else {
+                                       sel = 0.5;
+                               }
+                               break;
+                       case cmp_notequal:
+                               if (exp_is_atom(r) && !exp_is_atom(l)) {
+                                       prop *p = find_prop(l->p, 
PROP_NUNIQUES);
+                                       if (p && p->value.dval > 1)
+                                               sel = 1.0 - 1.0 / p->value.dval;
+                                       else
+                                               sel = 0.9;
+                               } else if (exp_is_atom(l) && !exp_is_atom(r)) {
+                                       prop *p = find_prop(r->p, 
PROP_NUNIQUES);
+                                       if (p && p->value.dval > 1)
+                                               sel = 1.0 - 1.0 / p->value.dval;
+                                       else
+                                               sel = 0.9;
+                               } else {
+                                       sel = 0.9;
+                               }
+                               break;
+                       case cmp_gt:
+                       case cmp_gte:
+                       case cmp_lt:
+                       case cmp_lte:
+                               sel = 0.50;
+                               break;
+                       case cmp_in:
+                       case cmp_notin: {
+                               list *vals = (list *) e->r;
+                               int nvals = list_length(vals);
+                               prop *p = find_prop(l->p, PROP_NUNIQUES);
+                               if (p && p->value.dval > 0) {
+                                       sel = (dbl) nvals / p->value.dval;
+                               } else {
+                                       sel = (dbl) nvals * 0.05;
+                               }
+                               if (sel > 0.5)
+                                       sel = 0.5;
+                               if (e->flag == cmp_notin)
+                                       sel = 1.0 - sel;
+                               break;
+                       }
+                       case cmp_con: {
+                                 list *lst = (list *) e->l;
+                                 sel = 1.0;
+                                 for (node *n = lst->h; n; n = n->next)
+                                         sel *= exp_estimate_selectivity(sql, 
(sql_exp *) n->data);
+                                 break;
+                       }
+                       case cmp_dis: {
+                                 list *lst = (list *) e->l;
+                                 sel = 0.0;
+                                 for (node *n = lst->h; n; n = n->next)
+                                 sel += exp_estimate_selectivity(sql, (sql_exp 
*) n->data);
+                                 if (sel > 1.0)
+                                         sel = 1.0;
+                                 break;
+                       }
+                       case cmp_filter:
+                                 sel = 0.01;
+                                 break;
+                       default:
+                                 sel = 0.1;
+                                 break;
+                       }
+               }
+               break;
+       }
+       case e_psm:
+               sel = 0.5;
+               break;
+       }
+       if (sel < 0.0)
+               sel = 0.0;
+       if (sel > 1.0)
+               sel = 1.0;
+       return sel;
+}
+
 bool
 exps_has_group_filter(list *exps)
 {
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
@@ -153,6 +153,7 @@ extern int exp_match( sql_exp *e1, sql_e
 extern sql_exp* exps_find_exp( list *l, sql_exp *e);
 extern int exp_match_exp( sql_exp *e1, sql_exp *e2);
 extern int exp_match_exp_semantics( sql_exp *e1, sql_exp *e2, bool semantics);
+extern int exp_match_exp_cmp( sql_exp *e1, sql_exp *e2 ); /* return 0 on match 
else !0 */
 extern sql_exp* exps_any_match(list *l, sql_exp *e);
 /* match just the column (cmp equality) expressions */
 extern int exp_match_col_exps( sql_exp *e, list *l);
@@ -211,6 +212,7 @@ extern sql_exp *exps_bind_column2(list *
 extern sql_exp * list_find_exp(const list *exps, sql_exp *e);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to