Changeset: acd2a88cf124 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=acd2a88cf124
Modified Files:
        sql/server/rel_optimizer.c
Branch: default
Log Message:

with a select under a mergetable we can reduce the partition list (Point cloud 
opt).


diffs (195 lines):

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
@@ -6330,10 +6330,44 @@ rel_add_dicts(int *changes, mvc *sql, sq
        return rel;
 }
 
+static int
+find_col_exp( list *exps, sql_exp *e)
+{
+       node *n;
+       int nr = 0; 
+
+       for (n=exps->h; n; n=n->next, nr++){
+               if (n->data == e)
+                       return nr;
+       }
+       return -1;
+}
+
+static int
+exp_range_overlap( mvc *sql, sql_exp *e, void *min, void *max, atom *emin, 
atom *emax)
+{
+       sql_subtype *t = exp_subtype(e);
+
+       if (t->type->localtype == TYPE_dbl) {
+               atom *cmin = atom_general(sql->sa, t, min);
+               atom *cmax = atom_general(sql->sa, t, max);
+
+               if (emax->d < cmin->data.val.dval || emin->d > 
cmax->data.val.dval)
+                       return 0;
+       }
+       return 1;
+}
+
 /* rewrite merge tables into union of base tables and call optimizer again */
 static sql_rel *
 rel_merge_table_rewrite(int *changes, mvc *sql, sql_rel *rel)
 {
+       sql_rel *sel = NULL;
+
+       if (is_select(rel->op) && rel->l) {
+               sel = rel;
+               rel = rel->l;
+       }
        if (is_basetable(rel->op) && rel->l) {
                sql_table *t = rel->l;
 
@@ -6341,45 +6375,123 @@ rel_merge_table_rewrite(int *changes, mv
                        /* instantiate merge tabel */
                        sql_rel *nrel = NULL;
                        char *tname = exp_find_rel_name(rel->exps->h->data);
-
-                       node *n;
+                       list *cols = NULL, *low = NULL, *high = NULL;
 
                        if (list_empty(t->tables.set)) 
                                return rel;
+                       if (sel) {
+                               node *n;
+
+                               /* no need to reduce the tables list */
+                               if (list_length(t->tables.set) < 100) 
+                                       return sel;
+
+                               cols = sa_list(sql->sa);
+                               low = sa_list(sql->sa);
+                               high = sa_list(sql->sa);
+                               for(n = sel->exps->h; n; n = n->next) {
+                                       sql_exp *e = n->data;   
+                                       atom *lval = NULL, *hval = NULL;
+
+                                       /* only ranges */
+                                       if (e->type == e_cmp && e->f) {
+                                               sql_exp *l = e->r;
+                                               sql_exp *h = e->f;
+                                               sql_exp *c = e->l;
+
+                                               c = rel_find_exp(rel, c);
+                                               if (l->type == e_atom && !l->l)
+                                                       lval = 
sql->args[l->flag];
+                                               if (h->type == e_atom && !h->l)
+                                                       hval = 
sql->args[h->flag];
+                                               if (c && lval && hval) {
+                                                       append(cols, c);
+                                                       append(low, lval);
+                                                       append(high, hval);
+                                               }
+                                       }
+                               }
+                       }
                        assert(!rel_is_ref(rel));
                        (*changes)++;
                        if (t->tables.set) {
-                               for (n = t->tables.set->h; n; n = n->next) {
-                                       sql_table *pt = n->data;
+                               list *tables = sa_list(sql->sa);
+                               node *nt;
+
+                               for (nt = t->tables.set->h; nt; nt = nt->next) {
+                                       sql_table *pt = nt->data;
                                        sql_rel *prel = rel_basetable(sql, pt, 
tname);
                                        node *n, *m;
+                                       int skip = 0;
+
+                                       /* do not include empty partitions */
+                                       if ((nrel || nt->next) && 
+                                          pt && isTable(pt) && pt->readonly && 
!store_funcs.count_col(sql->session->tr, pt->columns.set->h->data, 1)){
+                                               continue;
+                                       }
 
                                        /* rename (mostly the idxs) */
                                        MT_lock_set(&prel->exps->ht_lock, 
"rel_merge_table_rewrite");
                                        prel->exps->ht = NULL;
                                        MT_lock_unset(&prel->exps->ht_lock, 
"rel_merge_table_rewrite");
-                                       for (n = rel->exps->h, m = 
prel->exps->h; n && m; n = n->next, m = m->next ) {
+                                       for (n = rel->exps->h, m = 
prel->exps->h; n && m && !skip; n = n->next, m = m->next ) {
                                                sql_exp *e = n->data;
                                                sql_exp *ne = m->data;
-
+                                               int i;
+
+                                               if (pt && isTable(pt) && 
pt->readonly && sel && (nrel || nt->next) && (i=find_col_exp(cols, e)) != -1) {
+                                                       /* check if incase of 
an expression if the part falls within the bounds else skip this (keep at least 
on part-table) */
+                                                       void *min, *max;
+                                                       sql_column *col = NULL;
+                                                       sql_rel *bt = NULL;
+
+                                                       col = 
name_find_column(prel, e->l, e->r, -2, &bt);
+                                                       assert(col);
+                                                       if 
(sql_trans_ranges(sql->session->tr, col, &min, &max)) {
+                                                               atom *lval = 
list_fetch(low,i);
+                                                               atom *hval = 
list_fetch(high,i);
+
+                                                               if 
(!exp_range_overlap(sql, e, min, max, lval, hval))
+                                                                       skip = 
1;
+                                                       }
+                                               }
                                                exp_setname(sql->sa, ne, 
e->rname, e->name);
                                        }
-                                       if (nrel) { 
-                                               nrel = rel_setop(sql->sa, nrel, 
prel, op_union);
-                                               nrel->exps = 
rel_projections(sql, rel, NULL, 1, 1);
-                                       } else {
+                                       if (!skip) {
+                                               append(tables, prel);
                                                nrel = prel;
                                        }
                                }
+                               while (list_length(tables) > 1) {
+                                       list *ntables = sa_list(sql->sa);
+                                       node *n;
+
+                                       for(n=tables->h; n && n->next; n = 
n->next->next) {
+                                               sql_rel *l = n->data;
+                                               sql_rel *r = n->next->data;
+                                               nrel = rel_setop(sql->sa, l, r, 
op_union);
+                                               nrel->exps = 
rel_projections(sql, rel, NULL, 1, 1);
+                                               append(ntables, nrel);
+                                       }
+                                       if (n)
+                                               append(ntables, n->data);
+                                       tables = ntables;
+                               }
                        }
                        if (nrel && list_length(t->tables.set) == 1) {
                                nrel = rel_project(sql->sa, nrel, rel->exps);
                        } else if (nrel)
                                nrel->exps = rel->exps;
                        rel_destroy(rel);
+                       if (sel) {
+                               sel->l = nrel;
+                               return sel;
+                       }
                        return nrel;
                }
        }
+       if (sel)
+               return sel;
        return rel;
 }
 
@@ -7220,8 +7332,11 @@ static sql_rel *
        if (gp.cnt[op_join] || 
            gp.cnt[op_left] || gp.cnt[op_right] || gp.cnt[op_full] || 
            gp.cnt[op_semi] || gp.cnt[op_anti] ||
-           gp.cnt[op_select]) 
+           gp.cnt[op_select]) {
                rel = rewrite(sql, rel, &rel_push_func_down, &changes);
+               rel = rewrite_topdown(sql, rel, &rel_push_select_down, 
&changes); 
+               rel = rewrite(sql, rel, &rel_remove_empty_select, &e_changes); 
+       }
 
        if (!changes && gp.cnt[op_topn]) {
                rel = rewrite_topdown(sql, rel, &rel_push_topn_down, &changes); 
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to