Changeset: 2d127f2cc152 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=2d127f2cc152
Modified Files:
        monetdb5/optimizer/opt_centipede.mx
Branch: default
Log Message:

Simplify the centipede optimizer
The code produces a horizontal partitioning based on oid ranges.
The TPCH queries run correctly on non-remote version (except
for double column expression Q1)).


diffs (truncated from 355 to 300 lines):

diff --git a/monetdb5/optimizer/opt_centipede.mx 
b/monetdb5/optimizer/opt_centipede.mx
--- a/monetdb5/optimizer/opt_centipede.mx
+++ b/monetdb5/optimizer/opt_centipede.mx
@@ -152,7 +152,7 @@ OPTexecController(Client cntxt, MalBlkPt
                for ( k=0  ;k < nrpack ; k++){
                        pack[k] = newInstruction(cmb,ASSIGNsymbol);
                        getModuleId(pack[k]) = matRef;
-                       getFunctionId(pack[k]) = putName("pack3",5);
+                       getFunctionId(pack[k]) = packRef;
                        getArg(pack[k],0) = newTmpVariable(cmb, 
newBatType(TYPE_oid, getTailType(getArgType(cmb,p,k))) );
                }
        }
@@ -409,13 +409,13 @@ OPTsliceColumn(Client cntxt, MalBlkPtr n
  * when a connection is re-used by different client sessions.
 */
 #define BLOCKED 1
-#define REQUIRED 2
+#define PARTITION 2
 #define SUPPORTIVE 3
 #define EXPORTED 4
 #define KEEPLOCAL 5
 
 #ifdef _DEBUG_OPT_CENTIPEDE_ 
-static char *statusname[6]= {"", "blocked  ", "required ", "support  ", 
"exported ", "keeplocal "};
+static char *statusname[6]= {"", "blocked  ", "partition ", "support  ", 
"exported ", "keeplocal "};
 #endif
 
 static void 
@@ -469,200 +469,181 @@ OPTbakePlans(Client cntxt, MalBlkPtr mb,
 
        /* Phase 1: determine all variables/instructions indirectly dependent 
on a fragmented column */
        last = limit;
+       status[0]= PARTITION;
+       for ( j = old[0]->retc; j < old[0]->argc; j++)
+               vars[getArg(old[0],j)]= SUPPORTIVE;
        for ( i = 1; i < limit ; i++) {
                p = old[i];
                if ( p->token == ENDsymbol || i > last) {
-                       status[i] = REQUIRED;
+                       status[i] = PARTITION;
                        last = i;
                } else
                if ( getModuleId(p) == sqlRef && (getFunctionId(p) == bindRef 
|| getFunctionId(p) == bindidxRef) &&
                        strcmp(slices->schema, getVarConstant(mb, 
getArg(p,2)).val.sval) == 0 &&
                        strcmp(slices->table, getVarConstant(mb, 
getArg(p,3)).val.sval) == 0 ) {
-                       status[i] = REQUIRED;
+                       status[i] = PARTITION;
                        head[getArg(p,0)] = 1;
                        tail[getArg(p,0)] = getFunctionId(p) != bindidxRef;
                } 
 
-               /* blocking instructions are those that require data exchange 
or total view */
+               /* blocking instructions are those that require data exchange, 
aggregation or total view */
                if (    getModuleId(p) == algebraRef && getFunctionId(p) == 
joinRef ) {
                        /* be aware that supportive subqueries may produce 
pivot sets */
                        /* this means we have to enforce the following */
-                       if ( vars[getArg(p,1)] == REQUIRED && vars[getArg(p,2)] 
!= REQUIRED  ) {
-                               status[i] = SUPPORTIVE;
+                       if ( vars[getArg(p,1)] == PARTITION && 
vars[getArg(p,2)] != PARTITION  ) {
+                               status[i] = PARTITION;
                                head[getArg(p,0)] = 1;
-                       }
+                       } else
+                       if ( vars[getArg(p,1)] == PARTITION && 
vars[getArg(p,2)] == PARTITION  ) 
+                               status[i] = BLOCKED;
                } else
                if (    getModuleId(p) == algebraRef && getFunctionId(p) == 
leftjoinRef ) {
                                head[getArg(p,0)] = head[getArg(p,1)];
                                tail[getArg(p,0)] = tail[getArg(p,1)];
                                if ( head[getArg(p,0)] + tail[getArg(p,0)])
-                                       status[i] = REQUIRED;
+                                       status[i] = PARTITION;
                } else
                if (    getModuleId(p) == algebraRef && 
(getFunctionId(p)==markTRef || getFunctionId(p)== thetauselectRef) )  {
-                       if (vars[getArg(p,p->retc)] == REQUIRED ) {
+                       if (vars[getArg(p,p->retc)] == PARTITION ) {
                                head[getArg(p,0)] = 1;
-                               status[i] = REQUIRED;
+                               status[i] = PARTITION;
                        } 
                } else
                if (    getModuleId(p) == algebraRef && 
getFunctionId(p)==markHRef )  {
-                       if (vars[getArg(p,p->retc)] == REQUIRED )
+                       if (vars[getArg(p,p->retc)] == PARTITION )
                                tail[getArg(p,0)] = 1;
                } else
                if (    getModuleId(p) == batRef && 
getFunctionId(p)==reverseRef )  {
-                       if (vars[getArg(p,p->retc)] == REQUIRED ){
+                       if (vars[getArg(p,p->retc)] == PARTITION ){
                                head[getArg(p,0)] = tail[getArg(p,p->retc)];
                                tail[getArg(p,0)] = head[getArg(p,p->retc)];
-                               status[i] = REQUIRED;
+                               status[i] = PARTITION;
                        }
                } else
+               if (    getModuleId(p) == algebraRef && 
(getFunctionId(p)==sortRef || getFunctionId(p)==sortTailRef))  {
+                       /* this is always blocking */
+                       if (vars[getArg(p,p->retc)] == PARTITION )
+                               status[i]= BLOCKED;
+               } else
                if (   (getModuleId(p) == groupRef && (getFunctionId(p) == 
doneRef || getFunctionId(p) == newRef ||getFunctionId(p) == deriveRef) )  ||
                                getModuleId(p) == pqueueRef || getModuleId(p) 
== aggrRef ){
-                       /* this is blocking for partitioned columns, this can 
be achieved by propagating the REQUIRED property over variables */
-                       for( j = p->retc; j < p->argc; j++)
-                       if (vars[getArg(p,j)] == REQUIRED )
-                               break;
+                       /* this is always blocking */
+                       status[i]= BLOCKED;
+               } else
+               if (    (getModuleId(p) == sqlRef && (getFunctionId(p) == 
resultSetRef || getFunctionId(p) == putName("exportValue",11) ) )  ||
+                               getModuleId(p) == ioRef )
+                       status[i] = BLOCKED;
+               else 
+               if ( getModuleId(p) == batcalcRef ){
+                       if ( p->argc == 2 /* coercions and unaries */ && 
vars[getArg(p,1)] == PARTITION ) {
+                               status[i]= PARTITION;
+                               head[getArg(p,0)] = head[getArg(p,1)];
+                               tail[getArg(p,0)] = tail[getArg(p,1)];
+                       }
+                       if ( p->argc == 3 /* binaries */ && (vars[getArg(p,1)] 
== PARTITION || vars[getArg(p,2)] == PARTITION)) {
+                               status[i]= PARTITION;
+                               head[getArg(p,0)] = head[getArg(p,1)];
+                               tail[getArg(p,0)] = tail[getArg(p,1)];
+                       }
                } 
+               for( j = p->retc; j < p->argc; j++)
+               if (vars[getArg(p,j)] == BLOCKED ) 
+                       break;
+               if ( j != p->argc && p->argc - p->retc > 0 )
+                       status[i]= BLOCKED;
 
-               if( status[i] == BLOCKED){
-                       for ( j= 0; j< p->retc; j++)
-                               vars[getArg(p,j)] = BLOCKED;
-               } else {
-                       /* one blocking argument blocks the instruction */
-                       for( j = p->retc; j < p->argc; j++)
-                       if (vars[getArg(p,j)] == BLOCKED ) 
-                               break;
-                       if ( j != p->argc )
-                               status[i]= BLOCKED;
+               for ( j= 0; j< p->retc; j++)
+               if (vars[getArg(p,j)] == 0)
+                       vars[getArg(p,j)] = status[i];
 
-                       /* one required then instruction is needed */
-                       k = 0;
-                       for( j = p->retc; j < p->argc; j++)
-                       if (vars[getArg(p,j)] == REQUIRED )
-                               k++;
-                       if (k && k == p->argc-p->retc && status[i] != BLOCKED )
-                               status[i]= REQUIRED;
-                       else
-                       if ( k  && status[i] != BLOCKED )
-                               status[i] = REQUIRED;
+               if ( status[i] == PARTITION)
+               for( j = p->retc; j < p->argc; j++)
+               if (vars[getArg(p,j)] == 0)
+                       vars[getArg(p,j)] = SUPPORTIVE;
+       }
+#ifdef _DEBUG_OPT_CENTIPEDE_ 
+       mnstr_printf(cntxt->fdout,"\n#phase 1\n");
+       for( i= 0; i< limit; i++)
+       if (status[i] ) {
+               int x = old[i]->argv[0];
+               mnstr_printf(cntxt->fdout,"%s %d %s %c%c 
",statusname[status[i]], x, statusname[vars[x]], head[x]+'0', tail[x]+'0');
+               if( old[i])
+                       printInstruction(cntxt->fdout, 
mb,0,old[i],LIST_MAL_STMT);
+       }
+#endif
 
-                       for ( j= 0; j< p->retc; j++)
-                       if ( vars[getArg(p,j)] == 0)
-                               vars[getArg(p,j)] = status[i];
-               }
-       }
-
-       /* Phase 2: extend the set of supportive instructions.
+       /* Phase 2: extend the set with supportive instructions.
           we have to avoid common ancestor dependency on partitioned variables
        */
        for ( i = limit -1; i >= 0 ; i--)
-       if ( status[i] != BLOCKED ){
+       if ( status[i] == 0 ){
                p = old[i];
 
                for( j = 0; j < p->argc; j++)
-               if ( vars[getArg(p,j)] == SUPPORTIVE || vars[getArg(p,j)] == 
REQUIRED)  
+               if ( vars[getArg(p,j)] == BLOCKED)
                        break;
 
-               if( j< p->argc) {
-                       for ( j= p->retc; j< p->argc; j++)
-                       if ( vars[getArg(p,j)] != REQUIRED)
+               if ( j == p->argc ) {
+                       /* does it produce partitioned or support variables */
+                       for( j = 0; j < p->retc; j++)
+                       if ( vars[getArg(p,j)] == SUPPORTIVE || 
vars[getArg(p,j)] == PARTITION)  
+                               break;
+               } else {
+                       status[i] = BLOCKED;
+                       for( j = 0; j < p->retc; j++)
+                       if ( vars[getArg(p,j)] == 0)
+                               vars[getArg(p,j)] = BLOCKED;
+               }
+
+               if( j< p->retc && status[i] != BLOCKED ){
+                       for ( j= 0; j< p->argc; j++)
+                       if ( vars[getArg(p,j)] == 0)
                                vars[getArg(p,j)] = SUPPORTIVE;
-                       if ( status[i] != REQUIRED)
-                               status[i] = SUPPORTIVE;
-               }
-               /* be careful in adding operations that require exchange or 
full view */
-               if (    (getModuleId(p) == sqlRef && (getFunctionId(p) == 
resultSetRef || getFunctionId(p) == putName("exportValue",11) ) )  ||
-                               getModuleId(p) == ioRef )
+                       status[i] = SUPPORTIVE;
+               } else  {
+                       for ( j= 0; j< p->retc; j++)
+                       if ( vars[getArg(p,j)] == 0)
+                               vars[getArg(p,j)] = BLOCKED;
                        status[i] = BLOCKED;
-               if (getModuleId(p) == algebraRef && getFunctionId(p) == joinRef 
)  {
-                       /* if we produce an oid/oid based on the target, then 
we need an exchange */
-                       if ( head[getArg(p,1)] && tail[getArg(p,2)] )
-                               status[i] = BLOCKED;
-               }
-               if (    (getModuleId(p) == groupRef && (getFunctionId(p) == 
doneRef || getFunctionId(p) == newRef ||getFunctionId(p) == deriveRef) )  ||
-                               getModuleId(p) == pqueueRef || getModuleId(p) 
== aggrRef || getModuleId(p) == ioRef ) {
-                       /* this is blocking for partitioned columns, this can 
be achieved by propagating the REQUIRED property over variables */
-                       for( j = p->retc; j < p->argc; j++)
-                       if (vars[getArg(p,j)] == REQUIRED )
-                               break;
-                       if ( j != p->argc)
-                               status[i] = BLOCKED;
                }
        }
-       /* Phase 3: check all instructions for blocked arguments.
-          The variable may not be produced by a blocked instruction
-          and all arguments must be required/supportive/constant
-          (not blocked)
-       */
-       for ( i = 0; i < limit; i++) 
-       if( status[i] != 0){
-               p = old[i];
-               for( j = 0; j < p->argc; j++)
-               if (vars[getArg(p,j)] == BLOCKED)
-                       break;
-               if( j != p->argc || status[i] == BLOCKED) {
-                       status[i] = BLOCKED;
-                       for( j = 0; j < p->retc; j++)
-                               vars[getArg(p,j)] = BLOCKED;
-
-               }
-               for( j = 0; j < p->argc; j++)
-               if (vars[getArg(p,j)] == REQUIRED)
-                       break;
-               if( j != p->argc && status[i] != BLOCKED ) 
-                       for( j = 0; j < p->retc; j++)
-                               vars[getArg(p,j)] = REQUIRED;
-
-       }
 #ifdef _DEBUG_OPT_CENTIPEDE_ 
-       mnstr_printf(cntxt->fdout,"\n#phase 3\n");
+       mnstr_printf(cntxt->fdout,"\n#phase 2\n");
        for( i= 0; i< limit; i++)
        if (status[i] ) {
                int x = old[i]->argv[0];
-               mnstr_printf(cntxt->fdout,"%s %c%c ",statusname[status[i]], 
head[x]+'0', tail[x]+'0');
+               mnstr_printf(cntxt->fdout,"%s %s %c%c ",statusname[status[i]], 
statusname[vars[x]], head[x]+'0', tail[x]+'0');
                if( old[i])
                        printInstruction(cntxt->fdout, 
mb,0,old[i],LIST_MAL_STMT);
        }
 #endif
        /* Phase 4: determine all variables to be exported 
-          this is limited to all variables produced but not consumed
-          and only those that have an oid of the target
+          this is limited to all variables produced and consumed by a blocked 
instruction
        */
        ret= newInstruction(plan,ASSIGNsymbol);
        ret->barrier = RETURNsymbol;
        ret->argc= ret->retc = 0;
 
-       for ( i = limit-1; i >= 0 ; i--)
-       if ( status[i] == REQUIRED || status[i] == SUPPORTIVE ){
+       for ( i = 0; i< limit; i++)
+       if ( status[i] == BLOCKED  )
+       {
                p = old[i];
-               for ( j=0; j < p->retc; j++)
-               if ( vars[getArg(p,j)] == REQUIRED  && 
isaBatType(getArgType(plan,p,j)) )
-                               vars[getArg(p,j)] = EXPORTED;
-               else
-               if ( vars[getArg(p,j)] != 0 && vars[getArg(p,j)] != KEEPLOCAL  
&& vars[getArg(p,j)] != SUPPORTIVE && isaBatType(getArgType(plan,p,j)) ) {
+               for( j = p->retc; j < p->argc; j++)
+               if ( (vars[getArg(p,j)] == PARTITION || vars[getArg(p,j)] == 
SUPPORTIVE)  && isaBatType(getArgType(plan,p,j)) ){
                        /* limit the number of returned BATs to those that are 
expensive */
                        if ( (getModuleId(p) == algebraRef && (getFunctionId(p) 
== markHRef || getFunctionId(p) == markTRef)) ||
                                 (getModuleId(p) == batRef && (getFunctionId(p) 
== reverseRef || getFunctionId(p) == mirrorRef )) )
                                continue;
_______________________________________________
Checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list

Reply via email to