Changeset: 0b0cba05f046 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=0b0cba05f046
Modified Files:
        monetdb5/optimizer/opt_reorder.mx
        sql/backends/monet5/sql.mx
        sql/backends/monet5/sql_gencode.mx
        sql/benchmarks/ATIS/Tests/select_group.stable.out
        sql/benchmarks/tpch/LOCKED/Tests/01-22.stable.out
        sql/benchmarks/tpch/LOCKED/Tests/15.stable.out
        sql/benchmarks/tpch/Tests/01-22.stable.out
        sql/benchmarks/tpch/Tests/15.stable.out
        sql/include/sql_relation.h
        sql/server/bin_optimizer.c
        sql/server/rel_bin.c
        sql/server/rel_dump.c
        sql/server/rel_exp.c
        sql/server/rel_exp.h
        sql/server/rel_optimizer.c
        sql/server/rel_prop.c
        sql/server/rel_prop.h
        sql/server/rel_schema.c
        sql/server/rel_select.c
        sql/server/rel_select.h
        sql/server/rel_updates.c
        sql/server/rel_updates.h
        sql/server/sql_rel2bin.c
        sql/server/sql_statement.c
        sql/server/sql_statement.h
        sql/test/BugTracker-2011/Tests/groupby_primary_key.Bug-2807.stable.out
        sql/test/bugs/Tests/rangejoin_optimize_bug.stable.out
Branch: default
Log Message:

Partial reimplemented the reorder optimizer. The goal of the reimplementation
was more 'streaming'/io-pipelining of q1/q6 etc tpch like queries.
This is done making sure that 'a computed' bat's depending statements are
executed right after it, ie we try to limit the live time of intermediates.
(SF-100 q1 (partitioned) went down from >60 minutes to < 5 minutes)

fix in rel_select.c to make subqueries (with correlation) semijoins again.

added rewrites (or improved)
        push semijoin under groupby
        semi/antiJoin(a,join(a,b)) into semi/anti(a,b)
        antijoin(a,union(b,c)) into antijoin(antijoin(a,b),c)
        split groupby/projections (the sql compiler generates a single
        groupby in for example select avg(a)*5, this rewrites split this in
        a groupby and a project.

        reduce group by expressions based on primary key (ie if you already
        group by on a primary key, then extra columns of the same table
        do not reduce the groups anymore). We now join back these columns
        after the group by (with a join with the base table, basically late 
projection).
        Reduces the cost of q10 (of tpch).


diffs (truncated from 1924 to 300 lines):

diff --git a/monetdb5/optimizer/opt_reorder.mx 
b/monetdb5/optimizer/opt_reorder.mx
--- a/monetdb5/optimizer/opt_reorder.mx
+++ b/monetdb5/optimizer/opt_reorder.mx
@@ -83,14 +83,16 @@
 @c
 typedef struct{
        int cnt;
+       int used;
+       int pos,pos2;
        int stmt[];
 } *Node, NodeRecord;
 
 static Node *
-OPTdependencies(Client cntxt, MalBlkPtr mb){
+OPTdependencies(Client cntxt, MalBlkPtr mb, int **Ulist){
        Node *list = (Node *) GDKzalloc(sizeof(Node) * mb->stop);
-       int *var = (int*) GDKzalloc(sizeof(int) * mb->vtop);
-       int i,j;
+       int *var = (int*) GDKzalloc(sizeof(int) * mb->vtop), *uselist = NULL;
+       int i,j,sz=0;
        InstrPtr p = NULL;
        int block = 0;
        
@@ -113,70 +115,111 @@
                        GDKfree(var);
                        return 0;
                }
-               list[i]->cnt= p->argc;
-               for( j=p->retc; j<p->argc; j++)
-                       list[i]->stmt[j]= var[getArg(p,j)];
+               list[i]->cnt = p->argc;
+               for( j=p->retc; j<p->argc; j++) {
+                       list[i]->stmt[j] = var[getArg(p,j)];
+                       list[var[getArg(p,j)]]->used++;
+               }
                /* keep the assignment order */
-               for( j= 0; j < p->retc; j++)
-               if ( var[ getArg(p,j)] )
-                       list[i]->stmt[j] = var [getArg(p,j)];
-               /* remember the last assignment  */
+               for( j= 0; j < p->retc; j++) {
+                       if ( var[ getArg(p,j)] ) {
+                               //list[i]->stmt[j] = var [getArg(p,j)];
+                               // escape we should avoid reused variables.
+                               for (i--; i>=0; i--)
+                                       GDKfree(list[i]);
+                               GDKfree(list);
+                               GDKfree(var);
+                               return 0;
+                       }
+               }
+               /* remember the last assignment */
                for( j=0; j<p->retc; j++)
-                       var[getArg(p,j)]= i;
-               /* and also remember when it was last used.
-                  this would lead to more breath-first processing,
-                  something we want to avoid.
-               for( j=p->retc; j<p->argc; j++)
-                       var[getArg(p,j)]= i;
-               */
+                       var[getArg(p,j)] = i;
        }
 @-
        mnstr_printf(cntxt->fdout,"DEPENDENCY TABLE\n");
        for(i=0;i<mb->stop; i++)
-       if( list[i]->cnt){
-               mnstr_printf(cntxt->fdout,"[%d]",i);
-               for(j=p->retc; j< list[i]->cnt; j++)
-                       mnstr_printf(cntxt->fdout," %d",list[i]->stmt[j]);
+               if( list[i]->cnt){
+                       mnstr_printf(cntxt->fdout,"%s.%s [%d,%d]",
+                               mb->stmt[i]->modname,
+                               mb->stmt[i]->fcnname, i, list[i]->used);
+                       for(j=p->retc; j< list[i]->cnt; j++)
+                               mnstr_printf(cntxt->fdout, " %d", 
list[i]->stmt[j]);
+                       mnstr_printf(cntxt->fdout,"\n");
+               }
+@c
+       for(i=0;i<mb->stop; i++) {
+               list[i]->pos = sz;
+               list[i]->pos2 = sz;
+               sz += list[i]->used;
+       }
+       uselist = GDKzalloc(sizeof(int)*sz);
+
+       for(i=0;i<mb->stop; i++) {
+               if (list[i]->cnt) {
+                       p= getInstrPtr(mb,i);
+                       for(j=p->retc; j< list[i]->cnt; j++) {
+                               uselist[list[list[i]->stmt[j]]->pos2] = i;
+                               list[list[i]->stmt[j]]->pos2++;
+                       }
+               }
+       }
+@-
+       for(i=0, sz = 0; i<mb->stop; i++) {
+               mnstr_printf(cntxt->fdout,"%d is used by", i);
+               for(j=0; j<list[i]->used; j++, sz++)
+                       mnstr_printf(cntxt->fdout," %d", uselist[sz]);
                mnstr_printf(cntxt->fdout,"\n");
        }
 @c
+
        if ( block ){
                for (i--; i>=0; i--)
                        GDKfree(list[i]);
+               GDKfree(uselist);
                GDKfree(list);
                GDKfree(var);
                return NULL;
        }
        GDKfree(var);
+       *Ulist = uselist;
        return list;
 }
 
 static void
-OPTremoveDep(Node *list, int lim){
+OPTremoveDep(Node *list, int lim)
+{
        int i;
-       for( i=0; i< lim; i++)
-       if( list[i])
-               GDKfree(list[i]);
+
+       for (i=0; i< lim; i++)
+               if (list[i])
+                       GDKfree(list[i]);
        GDKfree(list);
 }
 
 static void
-OPTdepthfirst(Client cntxt, MalBlkPtr mb, int pc, InstrPtr old[], Node dep[])
+OPTbreadthfirst(Client cntxt, MalBlkPtr mb, int pc, int max, InstrPtr old[], 
Node dep[], int *uselist)
 {
        int i;
        InstrPtr p;
 
-       p= old[pc];
-       old[pc] = 0;
-       if( p == NULL)
+       if (pc > max)
                return;
-       for (i= 0; i< dep[pc]->cnt; i++)
-               OPTdepthfirst(cntxt, mb,dep[pc]->stmt[i], old, dep);
-               OPTDEBUGreorder{
-                       mnstr_printf(cntxt->fdout,"dump[%d]:",pc);
-                       printInstruction(cntxt->fdout,mb,0,p,LIST_MAL_STMT | 
LIST_MAPI);
-               }
-       pushInstruction(mb, p);
+
+       p = old[pc];
+       if (p == NULL)
+               return;
+
+       for (i= p->retc; i< dep[pc]->cnt; i++)
+               OPTbreadthfirst(cntxt, mb, dep[pc]->stmt[i], max, old, dep, 
uselist);
+       if (old[pc] != NULL) {
+               old[pc] = 0;
+               pushInstruction(mb, p);
+       }
+       if (getFunctionId(p) == leftjoinRef || getFunctionId(p) == newRef ||
+                       getFunctionId(p) == deriveRef || getFunctionId(p) == 
mirrorRef) 
+               for (i = 0; i< dep[pc]->used; i++)
+                       OPTbreadthfirst(cntxt, mb, uselist[dep[pc]->pos+i], 
max, old, dep, uselist);
 }
 
 static int
@@ -184,12 +227,12 @@
 {
        int i,j, start;
        InstrPtr *old;
-       int limit, slimit;
+       int limit, slimit, *uselist = NULL;
        Node *dep;
 
        (void) cntxt;
        (void) stk;
-       dep = OPTdependencies(cntxt,mb);
+       dep = OPTdependencies(cntxt,mb,&uselist);
        if ( dep == NULL)
                return 0;
        limit= mb->stop;
@@ -201,24 +244,28 @@
        pushInstruction(mb,old[0]);
        old[0]=0;
        for( i=1; i<limit; i++)
-       if ( getModuleId(old[i]) == datacyclotronRef && getFunctionId(old[i]) 
== bindRef){
-               pushInstruction(mb,old[i]);
-               old[i] = 0;
-       }
+               if ( getModuleId(old[i]) == datacyclotronRef && 
getFunctionId(old[i]) == bindRef){
+                       pushInstruction(mb,old[i]);
+                       old[i] = 0;
+               }
 
        start=1;
-       for( i=1; i<limit; i++){
+       for (i=1; i<limit; i++){
                p= old[i];
                if ( p == 0)
                        continue;
                if( p->token == ENDsymbol)
                        break;
-               if( hasSideEffects(p,TRUE) || (getModuleId(p) != sqlRef && 
isUpdateInstruction(p))  || isUnsafeFunction(p) || p->barrier ){
-                       OPTdepthfirst(cntxt, mb, i, old, dep);
+               if( hasSideEffects(p,FALSE) || isUnsafeFunction(p) || 
p->barrier ){
+                       OPTbreadthfirst(cntxt, mb, i, i, old, dep, uselist);
                        /* remove last instruction and keep for later */
-                       p= mb->stmt[mb->stop-1];
-                       mb->stmt[mb->stop-1]=0;
-                       mb->stop--;
+                       if (p == mb->stmt[mb->stop-1]) {
+                               p= mb->stmt[mb->stop-1];
+                               mb->stmt[mb->stop-1]=0;
+                               mb->stop--;
+                       } else {
+                               p = 0;
+                       }
                        /* collect all seen sofar by backward grouping */
                        /* since p has side-effects, we should secure all seen 
sofar */
                        for(j=i-1; j>=start;j--) {
@@ -226,9 +273,10 @@
                                        mnstr_printf(cntxt->fdout,"leftover: 
%d",start+1);
                                        
printInstruction(cntxt->fdout,mb,0,old[j],LIST_MAL_STMT | LIST_MAPI);
                                }
-                               OPTdepthfirst(cntxt, mb, j, old, dep);
+                               OPTbreadthfirst(cntxt, mb, j, i, old, dep, 
uselist);
                        }
-                       pushInstruction(mb,p);
+                       if (p)
+                               pushInstruction(mb,p);
                        start = i+1;
                }
        }
diff --git a/sql/backends/monet5/sql.mx b/sql/backends/monet5/sql.mx
--- a/sql/backends/monet5/sql.mx
+++ b/sql/backends/monet5/sql.mx
@@ -1455,6 +1455,7 @@
        b->currIndex = NULL;
        b->vtop = 0;
        b->q = NULL;
+       b->mvc_var = 0;
        return b;
 }
 
@@ -1466,6 +1467,7 @@
        b->console = isAdministrator(c);
        b->mvc = m;
        b->client = c;
+       b->mvc_var = 0;
        return backend_reset(b);
 }
 
diff --git a/sql/backends/monet5/sql_gencode.mx 
b/sql/backends/monet5/sql_gencode.mx
--- a/sql/backends/monet5/sql_gencode.mx
+++ b/sql/backends/monet5/sql_gencode.mx
@@ -577,6 +577,7 @@
                        if (s->op1) {
                                if (VAR_GLOBAL(s->flag)) { /* globals */
                                        int tt = tail_type(s)->type->localtype;
+
                                        q = newStmt1(mb, sqlRef, "getVariable");
                                        q = pushArgument(mb, q, sql->mvc_var);
                                        q = pushStr(mb, q, 
s->op1->op4.aval->data.val.sval);
diff --git a/sql/benchmarks/ATIS/Tests/select_group.stable.out 
b/sql/benchmarks/ATIS/Tests/select_group.stable.out
--- a/sql/benchmarks/ATIS/Tests/select_group.stable.out
+++ b/sql/benchmarks/ATIS/Tests/select_group.stable.out
@@ -37,7 +37,7 @@
 [ "SATURDAY",  6,      64      ]
 [ "SUNDAY",    7,      64      ]
 % sys.day_name,        sys.day_name # table_name
-% day_name,    L2 # name
+% day_name,    L3 # name
 % char,        wrd # type
 % 9,   2 # length
 [ "MONDAY",    64      ]
@@ -57,7 +57,7 @@
 [ "JULY",      "SUNDAY"        ]
 #select day_name.day_name,flight_day.day_code,count(*) from 
flight_day,day_name where day_name.day_code=flight_day.day_code group by 
flight_day.day_code,day_name.day_name order by day_code;
 % sys.day_name,        sys.flight_day, sys.flight_day # table_name
-% day_name,    day_code,       L3 # name
+% day_name,    day_code,       L4 # name
 % char,        decimal,        wrd # type
 % 9,   2,      2 # length
 [ "MONDAY",    1,      64      ]
@@ -68,57 +68,57 @@
 [ "SATURDAY",  6,      64      ]
 [ "SUNDAY",    7,      64      ]
 % sys.aircraft # table_name
-% L4 # name
+% L5 # name
 % decimal # type
 % 2 # length
 [ 278  ]
 % sys. # table_name
-% L5 # name
+% L6 # name
 % double # type
 % 22 # length
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to