Changeset: cd79b0ddfff3 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/cd79b0ddfff3
Modified Files:
        sql/backends/monet5/bin_partition_by_slice.c
        sql/backends/monet5/bin_partition_by_slice.h
        sql/backends/monet5/bin_partition_by_value.c
        sql/backends/monet5/bin_partition_by_value.h
        sql/backends/monet5/rel_physical.c
        sql/include/sql_relation.h
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimize_sel.c
        sql/server/rel_statistics.c
Branch: pp_hashjoin
Log Message:

disabled rel_push_join_down, causes crossproducts in tpcds.

improved cardinality estimation for somewhat


diffs (300 lines):

diff --git a/sql/backends/monet5/bin_partition_by_slice.c 
b/sql/backends/monet5/bin_partition_by_slice.c
--- a/sql/backends/monet5/bin_partition_by_slice.c
+++ b/sql/backends/monet5/bin_partition_by_slice.c
@@ -44,7 +44,9 @@ exp_getcard(mvc *sql, sql_rel *rel, sql_
        sql_subtype *t = exp_subtype(e);
        prop *p;
 
-       if ((p = find_prop(e->p, PROP_NUNIQUES)))
+       if (e->nuniques)
+               est = e->nuniques;
+       else if ((p = find_prop(e->p, PROP_NUNIQUES)))
                est = (BUN)p->value.dval;
 
        if (est == BUN_NONE
@@ -802,6 +804,60 @@ piggy_back(backend *be, sql_rel *rel, st
        }
 }
 
+bool
+rel_groupby_partition(mvc *sql, sql_rel *rel)
+{
+       bool partition = true;
+
+       for(node *n = rel->exps->h; n && partition; n = n->next ) {
+               sql_exp *e = n->data;
+
+               if (is_aggr(e->type)) {
+                       sql_subfunc *sf = e->f;
+
+                       /* for now only on complex aggregation */
+                       if (!(strcmp(sf->func->base.name, "min") == 0 || 
strcmp(sf->func->base.name, "max") == 0 ||
+                           strcmp(sf->func->base.name, "avg") == 0 || 
strcmp(sf->func->base.name, "count") == 0 ||
+                           strcmp(sf->func->base.name, "sum") == 0 || 
strcmp(sf->func->base.name, "prod") == 0)) {
+                               partition = false;
+                       }
+               }
+       }
+       if (!partition)
+               return false;
+       if (list_empty(rel->r))
+               return false;
+       /* check size */
+       BUN est = get_rel_count(rel);
+
+       lng estimate, card = 1;
+       if (est == BUN_NONE
+#if SIZEOF_BUN == SIZEOF_LNG
+               || (ulng) est > (ulng) GDK_lng_max
+#endif
+       )
+               estimate = 85000000;
+       else
+               estimate = (lng) est;
+       if (!list_empty(rel->r)) {
+               list *l = rel->r;
+               for( node *n = l->h; n; n = n->next ) {
+                       sql_exp *e = n->data;
+                       lng ncard = exp_getcard(sql, rel, e);
+                       card *= ncard; /* TODO check for overflow */
+                       if (card > estimate || ncard >= estimate) {
+                               card = estimate;
+                               break;
+                       }
+               }
+       }
+       if (card < estimate)
+               estimate = card;
+       if ((BUN)estimate >= 4*GDKL3_size)
+               return true;
+       return false;
+}
+
 stmt *
 rel2bin_groupby_pp(backend *be, sql_rel *rel, list *refs)
 {
@@ -812,7 +868,7 @@ rel2bin_groupby_pp(backend *be, sql_rel 
        stmt *sub = NULL, *cursub;
        stmt *groupby = NULL, *grp = NULL, *ext = NULL, *cnt_aggr = NULL;
        bool _2phases = rel_groupby_2_phases(be->mvc, rel);
-       bool value_partition = SQLrunning && rel->parallel && !_2phases && 
rel_groupby_partition(rel);
+       bool value_partition = SQLrunning && rel->parallel && !_2phases && 
rel_groupby_partition(be->mvc, rel);
        int neededpp = rel->partition && get_need_pipeline(be);
        int need_serialize = rel_groupby_serialize(rel); /* return if some of 
the aggregates require serialization (or fallback implementation) */
        sql_rel *inner = rel->l;
diff --git a/sql/backends/monet5/bin_partition_by_slice.h 
b/sql/backends/monet5/bin_partition_by_slice.h
--- a/sql/backends/monet5/bin_partition_by_slice.h
+++ b/sql/backends/monet5/bin_partition_by_slice.h
@@ -15,6 +15,7 @@
 #include "mal_backend.h"
 
 extern lng exp_getcard(mvc *sql, sql_rel *rel, sql_exp *e);
+extern bool rel_groupby_partition(mvc *sql, sql_rel *rel);
 extern stmt *rel2bin_groupby_pp(backend *be, sql_rel *rel, list *refs);
 
 #endif /*_BIN_SLICE_PARTITION_H_*/
diff --git a/sql/backends/monet5/bin_partition_by_value.c 
b/sql/backends/monet5/bin_partition_by_value.c
--- a/sql/backends/monet5/bin_partition_by_value.c
+++ b/sql/backends/monet5/bin_partition_by_value.c
@@ -159,38 +159,6 @@ rel2bin_slicer_pp(backend *be, stmt *sub
        }
 }
 
-bool
-rel_groupby_partition(sql_rel *rel)
-{
-       bool partition = true;
-
-       for(node *n = rel->exps->h; n && partition; n = n->next ) {
-               sql_exp *e = n->data;
-
-               if (is_aggr(e->type)) {
-                       sql_subfunc *sf = e->f;
-
-                       /* for now only on complex aggregation */
-                       if (!(strcmp(sf->func->base.name, "min") == 0 || 
strcmp(sf->func->base.name, "max") == 0 ||
-                           strcmp(sf->func->base.name, "avg") == 0 || 
strcmp(sf->func->base.name, "count") == 0 ||
-                           strcmp(sf->func->base.name, "sum") == 0 || 
strcmp(sf->func->base.name, "prod") == 0)) {
-                               partition = false;
-                       }
-               }
-       }
-       if (!partition)
-               return false;
-       if (list_empty(rel->r))
-               return false;
-       /* check size */
-       BUN est = get_rel_count(rel);
-       if (est == BUN_NONE)
-               return false;
-       if (est >= GDKL3_size)
-               return true;
-       return false;
-}
-
 /* part := part.new(nr_parts);
  * mat := mat.new(type:nil, nr_parts);
  */
diff --git a/sql/backends/monet5/bin_partition_by_value.h 
b/sql/backends/monet5/bin_partition_by_value.h
--- a/sql/backends/monet5/bin_partition_by_value.h
+++ b/sql/backends/monet5/bin_partition_by_value.h
@@ -18,8 +18,6 @@ extern int pp_dynamic_slices(backend *be
 //extern stmt *rel2bin_slicer(backend *be, stmt *sub);
 extern stmt *rel2bin_slicer_pp(backend *be, stmt *sub);
 
-extern bool rel_groupby_partition(sql_rel *rel);
-
 extern stmt *rel2bin_partition(backend *be, sql_rel *rel, list *refs);
 extern stmt *rel2bin_groupby_partition(backend *be, sql_rel *rel, list *refs, 
bool neededpp);
 
diff --git a/sql/backends/monet5/rel_physical.c 
b/sql/backends/monet5/rel_physical.c
--- a/sql/backends/monet5/rel_physical.c
+++ b/sql/backends/monet5/rel_physical.c
@@ -17,7 +17,7 @@
 #include "sql_storage.h"
 #include "sql_scenario.h"
 #include "rel_bin.h"
-#include "bin_partition_by_value.h"
+#include "bin_partition_by_slice.h"
 
 #define IS_ORDER_BASED_AGGR(fname, argc) (\
                                (argc == 2 && (strcmp((fname), "quantile") == 0 
|| strcmp((fname), "quantile_avg") == 0)) || \
@@ -646,7 +646,7 @@ rel_pipeline(visitor *v, sql_rel *rel, b
                }
        } else if (is_groupby(rel->op)) {
                bool safe = rel_groupby_partition_safe(rel);
-               if (safe && rel_groupby_partition(rel)) {
+               if (safe && rel_groupby_partition(v->sql, rel)) {
                        sql_rel *p = rel->l = rel_build_partition(v, rel->l);
                        p->attr = exps_copy(v->sql, rel->r);
                }
diff --git a/sql/include/sql_relation.h b/sql/include/sql_relation.h
--- a/sql/include/sql_relation.h
+++ b/sql/include/sql_relation.h
@@ -73,6 +73,7 @@ typedef struct expression {
        int shared;             /* shared variable */
        void *p;        /* properties for the optimizer */
        str comment;
+       ulng nuniques;
 } sql_exp;
 
 #define TABLE_PROD_FUNC                1
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
@@ -176,6 +176,8 @@ exp_compare(allocator *sa, sql_exp *l, s
        e->l = l;
        e->r = r;
        e->flag = cmptype;
+       if (cmptype == cmp_equal)
+               e->nuniques = 1;
        if (!has_nil(l) && !has_nil(r))
                set_has_no_nil(e);
        return e;
@@ -193,6 +195,8 @@ exp_compare2(allocator *sa, sql_exp *l, 
        e->r = r;
        e->f = f;
        e->flag = cmptype;
+       if (cmptype == cmp_equal)
+               e->nuniques = 1;
        if (symmetric)
                set_symmetric(e);
        if (!has_nil(l) && !has_nil(r) && !has_nil(f))
@@ -247,6 +251,8 @@ exp_in(allocator *sa, sql_exp *l, list *
        e->card = MAX(l->card, exps_card);
        e->l = l;
        e->r = r;
+       if (cmptype == cmp_in)
+               e->nuniques = list_length(r);
        assert( cmptype == cmp_in || cmptype == cmp_notin);
        e->flag = cmptype;
        if (!has_nil(l) && !have_nil(r))
@@ -1813,6 +1819,33 @@ exps_find_prop(list *exps, rel_prop kind
        return NULL;
 }
 
+sql_exp *
+predicates_find_nid(const list *exps, int nid)
+{
+       if (list_empty(exps))
+               return NULL;
+       for (node *n = exps->h ; n ; n = n->next) {
+               sql_exp *e = n->data;
+
+               if (e->type == e_cmp) {
+                       if (e->flag == cmp_filter) {
+                               ;
+                       } else if (e->flag == cmp_con || e->flag == cmp_dis) {
+                               ;
+                       } else if (e->flag == cmp_in || e->flag == cmp_notin) {
+                               sql_exp *l = e->l;
+                               if (l->nid == nid)
+                                       return e;
+                       } else {
+                               sql_exp *l = e->l;
+                               if (l->nid == nid)
+                                       return e;
+                       }
+               }
+       }
+       return NULL;
+}
+
 /* check is one of the exps can be found in this relation */
 static sql_exp* rel_find_exp_and_corresponding_rel_(sql_rel *rel, sql_exp *e, 
bool subexp, sql_rel **res);
 
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
@@ -209,6 +209,7 @@ extern sql_exp *exps_uses_nid(list *exps
 extern sql_exp *exps_bind_column(list *exps, const char *cname, int 
*ambiguous, int *multiple, int no_tname /* set if expressions should be without 
a tname */);
 extern sql_exp *exps_bind_column2(list *exps, const char *rname, const char 
*cname, int *multiple);
 extern sql_exp * list_find_exp(const list *exps, sql_exp *e);
+extern sql_exp *predicates_find_nid(const list *exps, int nid);
 
 extern unsigned int exps_card( list *l );
 extern void exps_fix_card( list *exps, unsigned int card);
diff --git a/sql/server/rel_optimize_sel.c b/sql/server/rel_optimize_sel.c
--- a/sql/server/rel_optimize_sel.c
+++ b/sql/server/rel_optimize_sel.c
@@ -3764,7 +3764,8 @@ rel_semijoin_use_fk(visitor *v, sql_rel 
 static inline sql_rel *
 rel_push_join_down(visitor *v, sql_rel *rel)
 {
-       if (!rel_is_ref(rel) && ((is_left(rel->op) || rel->op == op_join || 
is_semi(rel->op)) && rel->l && rel->exps)) {
+       /* needs work, currently causes crossproducts in tpcds 65 */
+       if (0 && !rel_is_ref(rel) && ((is_left(rel->op) || rel->op == op_join 
|| is_semi(rel->op)) && rel->l && rel->exps)) {
                sql_rel *gb = rel->r, *ogb = gb, *l = NULL, *rell = rel->l;
 
                if (is_simple_project(gb->op) && !rel_is_ref(gb))
@@ -3782,6 +3783,7 @@ rel_push_join_down(visitor *v, sql_rel *
                                int fnd = 0;
                                const char *rname = NULL, *name = NULL;
 
+                               /* TODO use nids! */
                                /* project in between, ie find alias */
                                /* first find expression in expression list */
                                gbe = exps_uses_exp( gb->exps, gbe);
diff --git a/sql/server/rel_statistics.c b/sql/server/rel_statistics.c
--- a/sql/server/rel_statistics.c
+++ b/sql/server/rel_statistics.c
@@ -60,6 +60,10 @@ rel_propagate_column_ref_statistics(mvc 
                                found_left = true;
                        if (!found_left && is_join(rel->op) && 
rel_propagate_column_ref_statistics(sql, rel->r, e))
                                found_right = true;
+                       sql_exp *ne;
+                       if ((ne = predicates_find_nid(rel->exps, e->nid)) != 
NULL) {
+                               e->nuniques = ne->nuniques;
+                       }
 
                        if (!found_left && !found_right)
                                return NULL;
@@ -180,6 +184,8 @@ rel_propagate_column_ref_statistics(mvc 
                        atom *fval;
                        prop *est;
                        if ((found = rel_find_exp(rel, e))) {
+                               if (found != e && !e->nuniques)
+                                       e->nuniques = found->nuniques;
                                if (found /*rel->op != op_table*/) { /* At the 
moment don't propagate statistics for table relations */
                                        if ((fval = find_prop_and_get(found->p, 
PROP_MAX)))
                                                set_minmax_property(sql, e, 
PROP_MAX, fval);
_______________________________________________
checkin-list mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to