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