]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Begin inserting some experimental code for the next generation query planner.
authordrh <drh@noemail.net>
Thu, 2 May 2013 00:15:01 +0000 (00:15 +0000)
committerdrh <drh@noemail.net>
Thu, 2 May 2013 00:15:01 +0000 (00:15 +0000)
FossilOrigin-Name: ccaf4c3f7e1ec45e058d594d9b5c26818a37722a

manifest
manifest.uuid
src/sqliteInt.h
src/where.c

index a5bd0b436bbc044cdf45afcc24c6884ed4217681..75d4e526f50f6b4049ec0b364cb00efb07a5c08a 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\snot\suse\sa\stransitive\sconstraint\sto\san\sIN\soperator\swhere\sthe\sRHS\sis\sa\nconstant\sif\sthere\sexists\sa\sdirect\s==\soperator\sto\sanother\stable\sin\san\souter\nloop.
-D 2013-05-01T17:58:35.871
+C Begin\sinserting\ssome\sexperimental\scode\sfor\sthe\snext\sgeneration\squery\splanner.
+D 2013-05-02T00:15:01.231
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in ce81671efd6223d19d4c8c6b88ac2c4134427111
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -194,7 +194,7 @@ F src/shell.c 5d527e5d08f05ec2c43ff194ea44bf62b974f4c9
 F src/sqlite.h.in 5a5a22a9b192d81a9e5dee00274e3a0484c4afb1
 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0
 F src/sqlite3ext.h d936f797812c28b81b26ed18345baf8db28a21a5
-F src/sqliteInt.h de835c584032769461c123a564381f9808542c0e
+F src/sqliteInt.h 0d76a0aa7c64536c6f55d11a8f9f40df0636af6a
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -263,7 +263,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
 F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
 F src/wal.h a4d3da523d55a226a0b28e9058ef88d0a8051887
 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
-F src/where.c 12d4200eb6ae991cad02367c391db076ac1af1b0
+F src/where.c fc62bea654f27d5787bc428cd8f3f176d764f785
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -1060,7 +1060,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P 329478cbed06f93652de50abdb31a6b41af02b9e
-R cc457983507eee39e1b071292dee5b26
+P faedaeace9c7ed9a8aaf96700caee09db0c0c061
+R 84f8c9b09f28282800936ed72686b19f
+T *branch * nextgen-query-plan-exp
+T *sym-nextgen-query-plan-exp *
+T -sym-trunk *
 U drh
-Z 944723cfd5dfa8d16765eaab2fd82886
+Z 18faca4b1f68b4b3514e189f395d77ff
index f88e8ae7a8a6668388e9041ae808fe69f8702cd8..016ae611b19a846ded76029fa879fcc93617b6d4 100644 (file)
@@ -1 +1 @@
-faedaeace9c7ed9a8aaf96700caee09db0c0c061
\ No newline at end of file
+ccaf4c3f7e1ec45e058d594d9b5c26818a37722a
\ No newline at end of file
index b041b3fb6e2476b263fd1ef28a417ebdb27a26b2..7a405b2fb12448f61192185c07e5eef09c9aeae8 100644 (file)
@@ -2065,6 +2065,7 @@ struct WhereInfo {
   int iBreak;               /* Jump here to break out of the loop */
   int nLevel;               /* Number of nested loop */
   struct WhereClause *pWC;  /* Decomposition of the WHERE clause */
+  struct WhereLoop *pLoops; /* List of all WhereLoop objects */
   double savedNQueryLoop;   /* pParse->nQueryLoop outside the WHERE loop */
   double nRowOut;           /* Estimated number of output rows */
   WhereLevel a[1];          /* Information about each nest loop in WHERE */
index 2de894c3e7d5a6be45f28effdc4978afadfa9803..f44ab496c075ac0f7b10b718bb038702a565d5e5 100644 (file)
@@ -39,6 +39,43 @@ typedef struct WhereMaskSet WhereMaskSet;
 typedef struct WhereOrInfo WhereOrInfo;
 typedef struct WhereAndInfo WhereAndInfo;
 typedef struct WhereCost WhereCost;
+typedef struct WhereLoop WhereLoop;
+typedef struct WherePath WherePath;
+typedef struct WhereTerm WhereTerm;
+
+/*
+** Each instance of this object represents a way of evaluating one
+** term of a join.  The WhereClause object holds a table of these
+** objects using (iTab,prereq,iOb,nOb) as the primary key.  Note that the
+** same join term might have multiple associated WhereLoop objects.
+*/
+struct WhereLoop {
+  Bitmask prereq;       /* Bitmask of other loops that must run first */
+  int iTab;             /* Index of the table coded by this loop */
+  u16 iOb, nOb;         /* ORDER BY terms satisfied by this strategy */
+  double rSetup;        /* One-time setup cost (ex: create transient index) */
+  double rRun;          /* Cost of running each loop */
+  double nOut;          /* Estimated number of output rows */
+  u32 wsFlags;          /* WHERE_* flags describing the plan */
+  u16 nEq;              /* Number of equality constraints */
+  u16 nTerm;            /* Number of entries in aTerm[] */
+  Index *pIndex;        /* Index used */
+  WhereTerm *aTerm;     /* WhereTerms used */
+  WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */
+};
+
+/*
+** Each instance of this object holds a sequence of WhereLoop objects
+** that implement some or all of the entire query plan.  
+*/
+struct WherePath {
+  Bitmask maskLoop;     /* Bitmask of all WhereLoop objects in this path */
+  double nRow;          /* Estimated number of rows generated by this path */
+  double rCost;         /* Total cost of this path */
+  WhereLoop *aLoop[1];  /* Array of WhereLoop objects implementing this path */
+  WherePath *pNextPath; /* Next path in order of increasing cost */
+  WherePath *pPrevPath; /* Previous path in cost order */
+};
 
 /*
 ** The query generator uses an array of instances of this structure to
@@ -91,7 +128,6 @@ typedef struct WhereCost WhereCost;
 ** in prereqRight and prereqAll.  The default is 64 bits, hence SQLite
 ** is only able to process joins with 64 or fewer tables.
 */
-typedef struct WhereTerm WhereTerm;
 struct WhereTerm {
   Expr *pExpr;            /* Pointer to the subexpression that is this term */
   int iParent;            /* Disable pWC->a[iParent] when this term disabled */
@@ -1793,9 +1829,9 @@ static void bestOrClauseIndex(WhereBestIdx *p){
       sBOI.pDistinct = 0;
       sBOI.ppIdxInfo = 0;
       for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
-        WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", 
+        /*WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", 
           (pOrTerm - pOrWC->a), (pTerm - pWC->a)
-        ));
+        ));*/
         if( (pOrTerm->eOperator& WO_AND)!=0 ){
           sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
           bestIndex(&sBOI);
@@ -1822,15 +1858,15 @@ static void bestOrClauseIndex(WhereBestIdx *p){
       /* If there is an ORDER BY clause, increase the scan cost to account 
       ** for the cost of the sort. */
       if( p->pOrderBy!=0 ){
-        WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
-                    rTotal, rTotal+nRow*estLog(nRow)));
+        /*WHERETRACE(("... sorting increases OR cost %.9g to %.9g\n",
+                    rTotal, rTotal+nRow*estLog(nRow)));*/
         rTotal += nRow*estLog(nRow);
       }
 
       /* If the cost of scanning using this OR term for optimization is
       ** less than the current cost stored in pCost, replace the contents
       ** of pCost. */
-      WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));
+      /*WHERETRACE(("... multi-index OR cost=%.9g nrow=%.9g\n", rTotal, nRow));*/
       if( rTotal<p->cost.rCost ){
         p->cost.rCost = rTotal;
         p->cost.used = used;
@@ -1927,8 +1963,8 @@ static void bestAutomaticIndex(WhereBestIdx *p){
   pWCEnd = &pWC->a[pWC->nTerm];
   for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
     if( termCanDriveIndex(pTerm, pSrc, p->notReady) ){
-      WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n",
-                    p->cost.rCost, costTempIdx));
+      /*WHERETRACE(("auto-index reduces cost from %.1f to %.1f\n",
+                    p->cost.rCost, costTempIdx));*/
       p->cost.rCost = costTempIdx;
       p->cost.plan.nRow = logN + 1;
       p->cost.plan.wsFlags = WHERE_TEMP_INDEX;
@@ -2113,7 +2149,7 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
   int nOrderBy;
   sqlite3_index_info *pIdxInfo;
 
-  WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName));
+  /*WHERETRACE(("Recomputing index info for %s...\n", pSrc->pTab->zName));*/
 
   /* Count the number of possible WHERE clause constraints referring
   ** to this virtual table */
@@ -2222,7 +2258,7 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
   int i;
   int rc;
 
-  WHERETRACE(("xBestIndex for %s\n", pTab->zName));
+  /*WHERETRACE(("xBestIndex for %s\n", pTab->zName));*/
   TRACE_IDX_INPUTS(p);
   rc = pVtab->pModule->xBestIndex(pVtab, p);
   TRACE_IDX_OUTPUTS(p);
@@ -2733,8 +2769,8 @@ static int whereRangeScanEst(
       }else{
         *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower);
       }
-      WHERETRACE(("range scan regions: %u..%u  div=%g\n",
-                  (u32)iLower, (u32)iUpper, *pRangeDiv));
+      /*WHERETRACE(("range scan regions: %u..%u  div=%g\n",
+                  (u32)iLower, (u32)iUpper, *pRangeDiv));*/
       return SQLITE_OK;
     }
   }
@@ -2791,7 +2827,7 @@ static int whereEqualScanEst(
   if( pRhs==0 ) return SQLITE_NOTFOUND;
   rc = whereKeyStats(pParse, p, pRhs, 0, a);
   if( rc==SQLITE_OK ){
-    WHERETRACE(("equality scan regions: %d\n", (int)a[1]));
+    /*WHERETRACE(("equality scan regions: %d\n", (int)a[1]));*/
     *pnRow = a[1];
   }
 whereEqualScanEst_cancel:
@@ -2837,7 +2873,7 @@ static int whereInScanEst(
   if( rc==SQLITE_OK ){
     if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
     *pnRow = nRowEst;
-    WHERETRACE(("IN row estimate: est=%g\n", nRowEst));
+    /*WHERETRACE(("IN row estimate: est=%g\n", nRowEst));*/
   }
   return rc;
 }
@@ -3049,10 +3085,10 @@ static int isSortingIndex(
     }else{
       Expr *pRight = pConstraint->pExpr->pRight;
       if( pRight->op==TK_COLUMN ){
-        WHERETRACE(("       .. isOrderedColumn(tab=%d,col=%d)",
-                    pRight->iTable, pRight->iColumn));
+        /*WHERETRACE(("       .. isOrderedColumn(tab=%d,col=%d)",
+                    pRight->iTable, pRight->iColumn));*/
         isEq = isOrderedColumn(p, pRight->iTable, pRight->iColumn);
-        WHERETRACE((" -> isEq=%d\n", isEq));
+        /*WHERETRACE((" -> isEq=%d\n", isEq));*/
 
         /* If the constraint is of the form X=Y where Y is an ordered value
         ** in an outer loop, then make sure the sort order of Y matches the
@@ -3319,10 +3355,10 @@ static void bestBtreeIndex(WhereBestIdx *p){
     WhereTerm *pFirstTerm = 0;    /* First term matching the index */
 #endif
 
-    WHERETRACE((
+    /*WHERETRACE((
       "   %s(%s):\n",
       pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk")
-    ));
+    ));*/
     memset(&pc, 0, sizeof(pc));
     pc.plan.nOBSat = nPriorSat;
 
@@ -3403,10 +3439,10 @@ static void bestBtreeIndex(WhereBestIdx *p){
     if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
       int bRev = 2;
       int bObUnique = 0;
-      WHERETRACE(("      --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
+      /*WHERETRACE(("      --> before isSortIndex: nPriorSat=%d\n",nPriorSat));*/
       pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
-      WHERETRACE(("      --> after  isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
-                  bRev, bObUnique, pc.plan.nOBSat));
+      /*WHERETRACE(("      --> after  isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
+                  bRev, bObUnique, pc.plan.nOBSat));*/
       if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
         pc.plan.wsFlags |= WHERE_ORDERED;
         if( bObUnique ) pc.plan.wsFlags |= WHERE_OB_UNIQUE;
@@ -3634,14 +3670,14 @@ static void bestBtreeIndex(WhereBestIdx *p){
     }
 
 
-    WHERETRACE((
+    /*WHERETRACE((
       "      nEq=%d nInMul=%d rangeDiv=%d bSort=%d bLookup=%d wsFlags=0x%08x\n"
       "      notReady=0x%llx log10N=%.1f nRow=%.1f cost=%.1f\n"
       "      used=0x%llx nOBSat=%d\n",
       pc.plan.nEq, nInMul, (int)rangeDiv, bSort, bLookup, pc.plan.wsFlags,
       p->notReady, log10N, pc.plan.nRow, pc.rCost, pc.used,
       pc.plan.nOBSat
-    ));
+    ));*/
 
     /* If this index is the best we have seen so far, then record this
     ** index and its cost in the p->cost structure.
@@ -3677,9 +3713,9 @@ static void bestBtreeIndex(WhereBestIdx *p){
        || p->cost.plan.u.pIdx==pSrc->pIndex 
   );
 
-  WHERETRACE(("   best index is %s cost=%.1f\n",
+  /*WHERETRACE(("   best index is %s cost=%.1f\n",
          p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
-         p->cost.rCost));
+         p->cost.rCost));*/
   
   bestOrClauseIndex(p);
   bestAutomaticIndex(p);
@@ -4928,6 +4964,13 @@ static int nQPlan = 0;              /* Next free slow in _query_plan[] */
 
 #endif /* SQLITE_TEST */
 
+/*
+** Delete a WhereLoop object
+*/
+static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
+  sqlite3DbFree(db, p->aTerm);
+  sqlite3DbFree(db, p);
+}
 
 /*
 ** Free a WhereInfo structure
@@ -4953,10 +4996,140 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
       }
     }
     whereClauseClear(pWInfo->pWC);
+    while( pWInfo->pLoops ){
+      WhereLoop *p = pWInfo->pLoops;
+      pWInfo->pLoops = p->pNextLoop;
+      whereLoopDelete(db, p);
+    }
     sqlite3DbFree(db, pWInfo);
   }
 }
 
+/*
+** Insert or replace a WhereLoop entry using the template supplied.
+**
+** An existing WhereLoop entry might be overwritten if the new template
+** is better and has fewer dependencies.  Or the template will be ignored
+** and no insert will occur if an existing WhereLoop is faster and has
+** fewer dependencies than the template.  Otherwise a new WhereLoop is
+** added based no the template.
+*/
+static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){
+  WhereLoop **ppPrev, *p;
+  sqlite3 *db = pWInfo->pParse->db;
+
+  /* Search for an existing WhereLoop to overwrite, or which takes
+  ** priority over pTemplate.
+  */
+  for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){
+    if( p->iTab!=pTemplate->iTab ) continue;
+    if( (p->prereq & pTemplate->prereq)==p->prereq
+     && p->nOb>=pTemplate->nOb
+     && p->iOb==pTemplate->iOb
+     && p->rSetup<=pTemplate->rSetup
+     && p->rRun<=pTemplate->rRun
+    ){
+      /* Already holding an equal or better WhereLoop.
+      ** Return without changing or adding anything */
+      return SQLITE_OK;
+    }
+    if( (p->prereq & pTemplate->prereq)==pTemplate->prereq
+     && p->nOb<=pTemplate->nOb
+     && p->iOb==pTemplate->iOb
+     && p->rSetup>=pTemplate->rSetup
+     && p->rRun>=pTemplate->rRun
+    ){
+      /* Overwrite an existing WhereLoop with a better one */
+      sqlite3DbFree(db, p->aTerm);
+      *ppPrev = p->pNextLoop;
+      break;
+    }
+  }
+
+  /* If we reach this point it means that either p[] should be overwritten
+  ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new
+  ** WhereLoop and insert it.
+  */
+  if( p==0 ){
+    p = sqlite3DbMallocRaw(db, sizeof(WhereLoop));
+    if( p==0 ) return SQLITE_NOMEM;
+  }
+  *p = *pTemplate;
+  p->pNextLoop = pWInfo->pLoops;
+  pWInfo->pLoops = p;
+  if( pTemplate->nTerm<=0 ) return SQLITE_OK;
+  p->aTerm = sqlite3DbMallocRaw(db, pTemplate->nTerm*sizeof(p->aTerm[0]));
+  if( p->aTerm==0 ){
+    p->nTerm = 0;
+    return SQLITE_NOMEM;
+  }
+  memcpy(p->aTerm, pTemplate->aTerm, pTemplate->nTerm*sizeof(p->aTerm[0]));
+  return SQLITE_OK;
+}
+
+/*
+** Add all WhereLoop objects for the iTab-th table of the join.  That
+** table is guaranteed to be a b-tree table, not a virtual table.
+*/
+static void whereLoopAddBtree(
+  WhereInfo *pWInfo,        /* WHERE clause information */
+  int iTab,                 /* The table to process */
+  Bitmask mExtra            /* Extra prerequesites for using this table */
+){
+  WhereLoop *pNew;          /* Template WhereLoop object */
+  sqlite3 *db = pWInfo->pParse->db;
+
+  pNew = sqlite3DbMallocZero(db, sizeof(*pNew));
+  if( pNew==0 ) return;
+  
+  /* Insert a full table scan */
+  pNew->iTab = iTab;
+  pNew->rSetup = (double)0;
+  pNew->rRun = (double)1000000;
+  pNew->nOut = (double)1000000;
+  whereLoopInsert(pWInfo, pNew);
+
+  whereLoopDelete(db, pNew);
+}
+
+/*
+** Add all WhereLoop objects for the iTab-th table of the join.  That
+** table is guaranteed to be a virtual table.
+*/
+static void whereLoopAddVirtual(
+  WhereInfo *pWInfo,        /* WHERE clause information */
+  int iTab,                 /* The table to process */
+  Bitmask mExtra            /* Extra prerequesites for using this table */
+){
+}
+
+/*
+** Add all WhereLoop objects for all tables 
+*/
+static void whereLoopAddAll(WhereInfo *pWInfo){
+  Bitmask mExtra = 0;
+  Bitmask mPrior = 0;
+  int iTab;
+  SrcList *pTabList = pWInfo->pTabList;
+  struct SrcList_item *pItem;
+  WhereClause *pWC = pWInfo->pWC;
+  sqlite3 *db = pWInfo->pParse->db;
+
+  /* Loop over the tables in the join, from left to right */
+  for(iTab=0, pItem=pTabList->a; iTab<pTabList->nSrc; iTab++, pItem++){
+    if( IsVirtual(pItem->pTab) ){
+      whereLoopAddVirtual(pWInfo, iTab, mExtra);
+    }else{
+      whereLoopAddBtree(pWInfo, iTab, mExtra);
+    }
+    mPrior |= getMask(pWC->pMaskSet, pItem->iCursor);
+    if( (pItem->jointype & (JT_LEFT|JT_CROSS))!=0 ){
+      mExtra = mPrior;
+    }
+    if( db->mallocFailed ) break;
+  }
+}
+
 
 /*
 ** Generate the beginning of the loop used for WHERE clause processing.
@@ -5187,6 +5360,35 @@ WhereInfo *sqlite3WhereBegin(
     pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
   }
 
+  /* Construct the WhereLoop objects */
+  WHERETRACE(("*** Optimizer Start ***\n"));
+  whereLoopAddAll(pWInfo);
+
+  /* Display all of the WhereLoop objects if wheretrace is enabled */
+#if defined(SQLITE_DEBUG) \
+    && (defined(SQLITE_TEST) || defined(SQLITE_ENABLE_WHERETRACE))
+  if( sqlite3WhereTrace ){
+    WhereLoop *p;
+    int nb = 2*((nTabList+15)/16);
+    for(p=pWInfo->pLoops; p; p=p->pNextLoop){
+      struct SrcList_item *pItem = pTabList->a + p->iTab;
+       Table *pTab = pItem->pTab;
+      sqlite3DebugPrintf("%02d.%0*llx", p->iTab, nb, p->prereq);
+      sqlite3DebugPrintf("     %s",
+                         pItem->zAlias ? pItem->zAlias : pTab->zName);
+      if( p->pIndex ){
+        sqlite3DebugPrintf(" index %s nEq %d", p->pIndex->zName, p->nEq);
+      }else{
+        sqlite3DebugPrintf("\n");
+      }
+      sqlite3DebugPrintf("     wsFlags %08x OB %d,%d nTerm %d\n",
+                         p->wsFlags, p->iOb, p->nOb, p->nTerm);
+      sqlite3DebugPrintf("     cost %.2e + %.2e nOut %.2e\n",
+                         p->prereq, p->rSetup, p->rRun, p->nOut);
+    }
+  }
+#endif
+
   /* Chose the best index to use for each table in the FROM clause.
   **
   ** This loop fills in the following fields:
@@ -5207,7 +5409,6 @@ WhereInfo *sqlite3WhereBegin(
   sWBI.n = nTabList;
   sWBI.pDistinct = pDistinct;
   andFlags = ~0;
-  WHERETRACE(("*** Optimizer Start ***\n"));
   for(sWBI.i=iFrom=0, pLevel=pWInfo->a; sWBI.i<nTabList; sWBI.i++, pLevel++){
     WhereCost bestPlan;         /* Most efficient plan seen so far */
     Index *pIdx;                /* Index for FROM table at pTabItem */
@@ -5221,7 +5422,7 @@ WhereInfo *sqlite3WhereBegin(
 
     memset(&bestPlan, 0, sizeof(bestPlan));
     bestPlan.rCost = SQLITE_BIG_DBL;
-    WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i));
+    /*WHERETRACE(("*** Begin search for loop %d ***\n", sWBI.i));*/
 
     /* Loop through the remaining entries in the FROM clause to find the
     ** next nested loop. The loop tests all FROM clause entries
@@ -5304,8 +5505,8 @@ WhereInfo *sqlite3WhereBegin(
         sWBI.notReady = (isOptimal ? m : sWBI.notValid);
         if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
   
-        WHERETRACE(("   === trying table %d (%s) with isOptimal=%d ===\n",
-                    j, sWBI.pSrc->pTab->zName, isOptimal));
+        /*WHERETRACE(("   === trying table %d (%s) with isOptimal=%d ===\n",
+                    j, sWBI.pSrc->pTab->zName, isOptimal));*/
         assert( sWBI.pSrc->pTab );
 #ifndef SQLITE_OMIT_VIRTUALTABLE
         if( IsVirtual(sWBI.pSrc->pTab) ){
@@ -5335,9 +5536,9 @@ WhereInfo *sqlite3WhereBegin(
           ** for the outer loop that table which benefits the least from
           ** being in the inner loop.  The following code scales the 
           ** outer loop cost estimate to accomplish that. */
-          WHERETRACE(("   scaling cost from %.1f to %.1f\n",
+          /*WHERETRACE(("   scaling cost from %.1f to %.1f\n",
                       sWBI.cost.rCost,
-                      sWBI.cost.rCost/pWInfo->a[j].rOptCost));
+                      sWBI.cost.rCost/pWInfo->a[j].rOptCost));*/
           sWBI.cost.rCost /= pWInfo->a[j].rOptCost;
         }
 
@@ -5367,11 +5568,11 @@ WhereInfo *sqlite3WhereBegin(
                 || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0))
             && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan))   /* (4) */
         ){
-          WHERETRACE(("   === table %d (%s) is best so far\n"
+          /*WHERETRACE(("   === table %d (%s) is best so far\n"
                       "       cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n",
                       j, sWBI.pSrc->pTab->zName,
                       sWBI.cost.rCost, sWBI.cost.plan.nRow,
-                      sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));
+                      sWBI.cost.plan.nOBSat, sWBI.cost.plan.wsFlags));*/
           bestPlan = sWBI.cost;
           bestJ = j;
         }
@@ -5388,11 +5589,11 @@ WhereInfo *sqlite3WhereBegin(
     testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
     testcase( bestJ>iFrom && bestJ<nTabList-1
                           && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
-    WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
+    /*WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
                 "    cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
                 bestJ, pTabList->a[bestJ].pTab->zName,
                 pLevel-pWInfo->a, bestPlan.rCost, bestPlan.plan.nRow,
-                bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));
+                bestPlan.plan.nOBSat, bestPlan.plan.wsFlags));*/
     if( (bestPlan.plan.wsFlags & WHERE_DISTINCT)!=0 ){
       assert( pWInfo->eDistinct==0 );
       pWInfo->eDistinct = WHERE_DISTINCT_ORDERED;