Changeset: 9261ee142d41 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=9261ee142d41
Modified Files:
        monetdb5/optimizer/opt_mergetable.c
        sql/backends/monet5/rel_bin.c
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimizer.c
Branch: Apr2019
Log Message:

also use count on candidates when we know the used column
is (unique or needs no distinct) and has no nils


diffs (240 lines):

diff --git a/monetdb5/optimizer/opt_mergetable.c 
b/monetdb5/optimizer/opt_mergetable.c
--- a/monetdb5/optimizer/opt_mergetable.c
+++ b/monetdb5/optimizer/opt_mergetable.c
@@ -989,7 +989,7 @@ aggr_phase2(char *aggr)
 static void
 mat_aggr(MalBlkPtr mb, InstrPtr p, mat_t *mat, int m)
 {
-       int tp = getArgType(mb,p,0), k, tp2 = TYPE_lng;
+       int tp = getArgType(mb,p,0), k, tp2 = TYPE_lng, i;
        int battp = (getModuleId(p)==aggrRef)?newBatType(tp):tp, battp2 = 0;
        int isAvg = (getFunctionId(p) == avgRef);
        InstrPtr r = NULL, s = NULL, q = NULL, u = NULL;
@@ -1013,6 +1013,8 @@ mat_aggr(MalBlkPtr mb, InstrPtr p, mat_t
                if (isAvg) 
                        q = pushReturn(mb, q, newTmpVariable(mb, tp2));
                q = pushArgument(mb,q,getArg(mat[m].mi,k));
+               for (i = q->argc; i<p->argc; i++)
+                       q = pushArgument(mb,q,getArg(p,i));
                pushInstruction(mb,q);
                
                r = pushArgument(mb,r,getArg(q,0));
@@ -1937,7 +1939,7 @@ OPTmergetableImplementation(Client cntxt
                 * Handle the rewrite v:=aggr.count(b) and sum()
                 * And the min/max is as easy
                 */
-               if (match == 1 && p->argc == 2 &&
+               if (match == 1 && p->argc >= 2 &&
                   ((getModuleId(p)==aggrRef &&
                        (getFunctionId(p)== countRef || 
                         getFunctionId(p)== count_no_nilRef || 
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
@@ -359,6 +359,23 @@ exp_list(backend *be, list *exps, stmt *
        return stmt_list(be, nl);
 }
 
+static stmt *
+exp_count_no_nil_arg( sql_exp *e, stmt *ext, sql_exp *ae, stmt *as ) 
+{
+       /* small optimization, ie use candidates directly on count(*) */
+       if (!need_distinct(e) && !ext && as && (!need_no_nil(e) || !ae || 
!has_nil(ae))) { 
+               /* skip alias statements */
+               while (as->type == st_alias)
+                       as = as->op1;
+               /* use candidate */
+               if (as && as->type == st_join && as->flag == cmp_project) {
+                       if (as->op1 && (as->op1->type != st_result || 
as->op1->op1->type != st_group)) /* exclude a subquery with select distinct 
under the count */
+                               as = as->op1;
+               }
+       }
+       return as;
+}
+
 stmt *
 exp_bin(backend *be, sql_exp *e, stmt *left, stmt *right, stmt *grp, stmt 
*ext, stmt *cnt, stmt *sel) 
 {
@@ -592,6 +609,8 @@ exp_bin(backend *be, sql_exp *e, stmt *l
 
                                if (as && as->nrcols <= 0 && left) 
                                        as = stmt_const(be, 
bin_first_column(be, left), as);
+                               if (en == attr->h && !en->next && 
exp_aggr_is_count(e))
+                                       as = exp_count_no_nil_arg(e, ext, at, 
as);
                                /* insert single value into a column */
                                if (as && as->nrcols <= 0 && !left)
                                        as = const_column(be, as);
@@ -616,17 +635,7 @@ exp_bin(backend *be, sql_exp *e, stmt *l
                                as = grp;
                        } else if (left) {
                                as = bin_first_column(be, left);
-                               /* small optimization, ie use candidates 
directly on count(*) */
-                               if (!need_distinct(e) && !ext && 
!need_no_nil(e) && as) { 
-                                       /* skip alias statements */
-                                       while (as->type == st_alias)
-                                               as = as->op1;
-                                       /* use candidate */
-                                       if (as && as->type == st_join && 
as->flag == cmp_project) {
-                                               if (as->op1 && (as->op1->type 
!= st_result || as->op1->op1->type != st_group)) /* exclude a subquery with 
select distinct under the count */
-                                                       as = as->op1;
-                                       }
-                               }
+                               as = exp_count_no_nil_arg(e, ext, NULL, as);
                        } else {
                                /* create dummy single value in a column */
                                as = stmt_atom_lng(be, 0);
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
@@ -2123,3 +2123,11 @@ create_table_part_atom_exp(mvc *sql, sql
                GDKfree(buf);
        return res;
 }
+
+int 
+exp_aggr_is_count(sql_exp *e)
+{
+       if (e->type == e_aggr && strcmp(((sql_subaggr *)e->f)->aggr->base.name, 
"count") == 0)
+               return 1;
+       return 0;
+}
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
@@ -155,4 +155,5 @@ extern void exp_sum_scales(sql_subfunc *
 
 extern sql_exp *create_table_part_atom_exp(mvc *sql, sql_subtype tpe, ptr 
value);
 
+extern int exp_aggr_is_count(sql_exp *e);
 #endif /* _REL_EXP_H_ */
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
@@ -41,6 +41,24 @@ static sql_rel * rel_remove_empty_select
 
 static sql_subfunc *find_func( mvc *sql, char *name, list *exps );
 
+static int
+exps_unique( list *exps )
+{
+       node *n;
+
+       if ((n = exps->h) != NULL) {
+               sql_exp *e = n->data;
+               prop *p;
+
+               if (e && (p = find_prop(e->p, PROP_HASHCOL)) != NULL) {
+                       sql_ukey *k = p->value;
+                       if (k && list_length(k->k.columns) <= 1)
+                               return 1;
+               }
+       }
+       return 0;
+}
+
 /* The important task of the relational optimizer is to optimize the
    join order. 
 
@@ -1764,8 +1782,7 @@ rel_push_count_down(int *changes, mvc *s
        if (is_groupby(rel->op) && !rel_is_ref(rel) &&
             r && !r->exps && r->op == op_join && !(rel_is_ref(r)) && 
            /* currently only single count aggregation is handled, no other 
projects or aggregation */
-           list_length(rel->exps) == 1 && ((sql_exp *) 
rel->exps->h->data)->type == e_aggr &&
-            strcmp(((sql_subaggr *) ((sql_exp *) 
rel->exps->h->data)->f)->aggr->base.name, "count") == 0) {
+           list_length(rel->exps) == 1 && 
exp_aggr_is_count(rel->exps->h->data)) {
                sql_exp *nce, *oce;
                sql_rel *gbl, *gbr;             /* Group By */
                sql_rel *cp;                    /* Cross Product */
@@ -1960,8 +1977,7 @@ rel_simplify_fk_joins(int *changes, mvc 
        while (is_groupby(rel->op) && !rel_is_ref(rel) &&
             r && r->exps && is_join(r->op) && list_length(r->exps) == 1 && 
!(rel_is_ref(r)) && 
            /* currently only single count aggregation is handled, no other 
projects or aggregation */
-           list_length(rel->exps) == 1 && ((sql_exp *) 
rel->exps->h->data)->type == e_aggr &&
-            strcmp(((sql_subaggr *) ((sql_exp *) 
rel->exps->h->data)->f)->aggr->base.name, "count") == 0) {
+           list_length(rel->exps) == 1 && 
exp_aggr_is_count(rel->exps->h->data)) {
                sql_rel *or = r;
 
                r = rel_simplify_count_fk_join(changes, sql, r, rel->exps);
@@ -2383,25 +2399,6 @@ exp_push_down_prj(mvc *sql, sql_exp *e, 
        return NULL;
 }
 
-/* TODO: check for keys with more than one colun */
-static int
-exps_unique( list *exps )
-{
-       node *n;
-
-       if ((n = exps->h) != NULL) {
-               sql_exp *e = n->data;
-               prop *p;
-
-               if (e && (p = find_prop(e->p, PROP_HASHCOL)) != NULL) {
-                       sql_ukey *k = p->value;
-                       if (k && list_length(k->k.columns) <= 1)
-                               return 1;
-               }
-       }
-       return 0;
-}
-
 static sql_rel *
 rel_distinct_project2groupby(int *changes, mvc *sql, sql_rel *rel)
 {
@@ -3948,7 +3945,7 @@ rel_push_aggr_down(int *changes, mvc *sq
 
                        if (oa->type == e_aggr) {
                                sql_subaggr *f = oa->f;
-                               int cnt = strcmp(f->aggr->base.name,"count")==0;
+                               int cnt = exp_aggr_is_count(oa);
                                sql_subaggr *a = sql_bind_aggr(sql->sa, 
sql->session->schema, (cnt)?"sum":f->aggr->base.name, exp_subtype(e));
 
                                assert(a);
@@ -4062,7 +4059,7 @@ gen_push_groupby_down(int *changes, mvc 
                                /* check args are part of left/right */
                                if (!list_empty(args) && rel_has_exps(cr, args) 
< 0)
                                        return rel;
-                               if (rel->op != op_join && 
strcmp(((sql_subaggr*)ce->f)->aggr->base.name, "count") == 0)
+                               if (rel->op != op_join && exp_aggr_is_count(ce))
                                        ce->p = prop_create(sql->sa, 
PROP_COUNT, ce->p);
                                list_append(aggrs, ce); 
                        }
@@ -5397,7 +5394,7 @@ rel_groupby_distinct2(int *changes, mvc 
                } else if (e->type == e_aggr && !need_distinct(e)) {
                        sql_exp *v;
                        sql_subaggr *f = e->f;
-                       int cnt = strcmp(f->aggr->base.name,"count")==0;
+                       int cnt = exp_aggr_is_count(e);
                        sql_subaggr *a = sql_bind_aggr(sql->sa, 
sql->session->schema, (cnt)?"sum":f->aggr->base.name, exp_subtype(e));
 
                        append(aggrs, e);
@@ -5431,6 +5428,20 @@ rel_groupby_distinct2(int *changes, mvc 
 static sql_rel *
 rel_groupby_distinct(int *changes, mvc *sql, sql_rel *rel) 
 {
+       if (is_groupby(rel->op) && !rel_is_ref(rel) && rel->exps && 
list_empty(rel->r)) { 
+               node *n;
+
+               for (n = rel->exps->h; n; n = n->next) {
+                       sql_exp *e = n->data;
+
+                       if (exp_aggr_is_count(e) && need_distinct(e)) {
+                               /* if count over unique values (ukey/pkey) */
+                               if (e->l && exps_unique(e->l))
+                                       set_nodistinct(e);
+                       }
+               }
+       }
+
        if (is_groupby(rel->op)) {
                sql_rel *l = rel->l;
                if (!l || is_groupby(l->op))
@@ -9331,7 +9342,7 @@ rel_apply_rewrite(int *changes, mvc *sql
                        sql_exp *e = n->data;
 
                        /* count_nil(*) -> count(t.TID) */
-                       if (!has_gbe && e->type == e_aggr && 
strcmp(((sql_subaggr *)e->f)->aggr->base.name, "count") == 0 && !e->l) {
+                       if (!has_gbe && exp_aggr_is_count(e) && !e->l) {
                                sql_rel *rl = r->l;
                                sql_exp *col = NULL;
                                list *l = new_exp_list(sql->sa);
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to