/ Check-in [9e810967]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:First attempt to store costs and row counts as a logarithm.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | nextgen-query-plan-logcost
Files: files | file ages | folders
SHA1: 9e8109673c3a87e379f5a5a97a8b0d5a1afe853d
User & Date: drh 2013-06-10 19:12:39
Context
2013-06-10
20:46
Fix some minor issues with logarithmic cost in NGQP. check-in: 69cf8772 user: drh tags: nextgen-query-plan-logcost
19:12
First attempt to store costs and row counts as a logarithm. check-in: 9e810967 user: drh tags: nextgen-query-plan-logcost
14:56
Simplification and performance tweak to the high-speed NGQP bypass. check-in: 0f8a38ee user: drh tags: nextgen-query-plan-exp
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/where.c.

    41     41   typedef struct WhereAndInfo WhereAndInfo;
    42     42   typedef struct WhereLevel WhereLevel;
    43     43   typedef struct WhereLoop WhereLoop;
    44     44   typedef struct WherePath WherePath;
    45     45   typedef struct WhereTerm WhereTerm;
    46     46   typedef struct WhereLoopBuilder WhereLoopBuilder;
    47     47   typedef struct WhereScan WhereScan;
    48         -typedef float WhereCost;
           48  +typedef unsigned short int WhereCost;  /* 10 times log2() of run-time */
    49     49   
    50     50   /*
    51     51   ** For each nested loop in a WHERE clause implementation, the WhereInfo
    52     52   ** structure contains a single instance of this structure.  This structure
    53     53   ** is intended to be private to the where.c module and should not be
    54     54   ** access or modified by other modules.
    55     55   **
................................................................................
  1815   1815         /* This index implies that the DISTINCT qualifier is redundant. */
  1816   1816         return 1;
  1817   1817       }
  1818   1818     }
  1819   1819   
  1820   1820     return 0;
  1821   1821   }
         1822  +
         1823  +/* 
         1824  +** The sum of two WhereCosts
         1825  +*/
         1826  +static WhereCost whereCostAdd(WhereCost a, WhereCost b){
         1827  +  static const unsigned char x[] = {
         1828  +     10, 10,                         /* 0,1 */
         1829  +      9, 9,                          /* 2,3 */
         1830  +      8, 8,                          /* 4,5 */
         1831  +      7, 7, 7,                       /* 6,7,8 */
         1832  +      6, 6, 6,                       /* 9,10,11 */
         1833  +      5, 5, 5,                       /* 12-14 */
         1834  +      4, 4, 4, 4,                    /* 15-18 */
         1835  +      3, 3, 3, 3, 3, 3,              /* 19-24 */
         1836  +      2, 2, 2, 2, 2, 2, 2,           /* 25-31 */
         1837  +  };
         1838  +  if( a>=b ){
         1839  +    if( a>b+49 ) return a;
         1840  +    if( a>b+31 ) return a+1;
         1841  +    return a+x[a-b];
         1842  +  }else{
         1843  +    if( b>a+49 ) return b;
         1844  +    if( b>a+31 ) return b+1;
         1845  +    return b+x[b-a];
         1846  +  }
         1847  +}
         1848  +
         1849  +/*
         1850  +** Convert an integer into a WhereCost
         1851  +*/
         1852  +static WhereCost whereCostFromInt(tRowcnt x){
         1853  +  static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
         1854  +  WhereCost y = 40;
         1855  +  if( x<8 ){
         1856  +    if( x<2 ) return 0;
         1857  +    while( x<8 ){  y -= 10; x <<= 1; }
         1858  +  }else{
         1859  +    while( x>255 ){ y += 40; x >>= 4; }
         1860  +    while( x>15 ){  y += 10; x >>= 1; }
         1861  +  }
         1862  +  return a[x&7] + y - 10;
         1863  +}
  1822   1864   
  1823   1865   /*
  1824   1866   ** Prepare a crude estimate of the logarithm of the input value.
  1825   1867   ** The results need not be exact.  This is only used for estimating
  1826   1868   ** the total cost of performing operations with O(logN) or O(NlogN)
  1827   1869   ** complexity.  Because N is just a guess, it is no great tragedy if
  1828   1870   ** logN is a little off.
  1829   1871   */
  1830   1872   static WhereCost estLog(WhereCost N){
  1831         -  u32 a;
  1832         -  assert( sizeof(WhereCost)==4 );  /* 32-bit float input */
  1833         -  if( N<=0.0 ) return 0.0;
  1834         -  memcpy(&a, &N, 4);
  1835         -  return ((a >>= 23)-127)*0.3;
         1873  +  return whereCostFromInt(N) - 33;
  1836   1874   }
  1837   1875   
  1838   1876   /*
  1839   1877   ** Two routines for printing the content of an sqlite3_index_info
  1840   1878   ** structure.  Used for testing and debugging only.  If neither
  1841   1879   ** SQLITE_TEST or SQLITE_DEBUG are defined, then these routines
  1842   1880   ** are no-ops.
................................................................................
  2236   2274     tRowcnt *aStat              /* OUT: stats written here */
  2237   2275   ){
  2238   2276     tRowcnt n;
  2239   2277     IndexSample *aSample;
  2240   2278     int i, eType;
  2241   2279     int isEq = 0;
  2242   2280     i64 v;
  2243         -  WhereCost r, rS;
         2281  +  double r, rS;
  2244   2282   
  2245   2283     assert( roundUp==0 || roundUp==1 );
  2246   2284     assert( pIdx->nSample>0 );
  2247   2285     if( pVal==0 ) return SQLITE_ERROR;
  2248   2286     n = pIdx->aiRowEst[0];
  2249   2287     aSample = pIdx->aSample;
  2250   2288     eType = sqlite3_value_type(pVal);
................................................................................
  2492   2530         ){
  2493   2531           iUpper = a[0];
  2494   2532           if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
  2495   2533         }
  2496   2534         sqlite3ValueFree(pRangeVal);
  2497   2535       }
  2498   2536       if( rc==SQLITE_OK ){
  2499         -      if( iUpper<=iLower ){
  2500         -        *pRangeDiv = (WhereCost)p->aiRowEst[0];
  2501         -      }else{
  2502         -        *pRangeDiv = (WhereCost)p->aiRowEst[0]/(WhereCost)(iUpper - iLower);
         2537  +      WhereCost iBase = whereCostFromInt(p->aiRowEst[0]);
         2538  +      if( iUpper>iLower ){
         2539  +        iBase -= whereCostFromInt(iUpper - iLower);
  2503   2540         }
         2541  +      *pRangeDiv = iBase;
  2504   2542         /*WHERETRACE(("range scan regions: %u..%u  div=%g\n",
  2505   2543                     (u32)iLower, (u32)iUpper, *pRangeDiv));*/
  2506   2544         return SQLITE_OK;
  2507   2545       }
  2508   2546     }
  2509   2547   #else
  2510   2548     UNUSED_PARAMETER(pParse);
  2511   2549     UNUSED_PARAMETER(p);
  2512   2550     UNUSED_PARAMETER(nEq);
  2513   2551   #endif
  2514   2552     assert( pLower || pUpper );
  2515         -  *pRangeDiv = (WhereCost)1;
  2516         -  if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (WhereCost)4;
  2517         -  if( pUpper ) *pRangeDiv *= (WhereCost)4;
         2553  +  *pRangeDiv = 0;
         2554  +  if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){
         2555  +    *pRangeDiv += 20;  assert( 20==whereCostFromInt(4) );
         2556  +  }
         2557  +  if( pUpper ){
         2558  +    *pRangeDiv += 20;  assert( 20==whereCostFromInt(4) );
         2559  +  }
  2518   2560     return rc;
  2519   2561   }
  2520   2562   
  2521   2563   #ifdef SQLITE_ENABLE_STAT3
  2522   2564   /*
  2523   2565   ** Estimate the number of rows that will be returned based on
  2524   2566   ** an equality constraint x=VALUE and where that VALUE occurs in
................................................................................
  2536   2578   ** for a UTF conversion required for comparison.  The error is stored
  2537   2579   ** in the pParse structure.
  2538   2580   */
  2539   2581   static int whereEqualScanEst(
  2540   2582     Parse *pParse,       /* Parsing & code generating context */
  2541   2583     Index *p,            /* The index whose left-most column is pTerm */
  2542   2584     Expr *pExpr,         /* Expression for VALUE in the x=VALUE constraint */
  2543         -  WhereCost *pnRow     /* Write the revised row estimate here */
         2585  +  tRowcnt *pnRow       /* Write the revised row estimate here */
  2544   2586   ){
  2545   2587     sqlite3_value *pRhs = 0;  /* VALUE on right-hand side of pTerm */
  2546   2588     u8 aff;                   /* Column affinity */
  2547   2589     int rc;                   /* Subfunction return code */
  2548   2590     tRowcnt a[2];             /* Statistics */
  2549   2591   
  2550   2592     assert( p->aSample!=0 );
................................................................................
  2585   2627   ** for a UTF conversion required for comparison.  The error is stored
  2586   2628   ** in the pParse structure.
  2587   2629   */
  2588   2630   static int whereInScanEst(
  2589   2631     Parse *pParse,       /* Parsing & code generating context */
  2590   2632     Index *p,            /* The index whose left-most column is pTerm */
  2591   2633     ExprList *pList,     /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
  2592         -  WhereCost *pnRow     /* Write the revised row estimate here */
         2634  +  tRowcnt *pnRow       /* Write the revised row estimate here */
  2593   2635   ){
  2594   2636     int rc = SQLITE_OK;         /* Subfunction return code */
  2595         -  WhereCost nEst;                /* Number of rows for a single term */
  2596         -  WhereCost nRowEst = (WhereCost)0; /* New estimate of the number of rows */
         2637  +  tRowcnt nEst;           /* Number of rows for a single term */
         2638  +  tRowcnt nRowEst = 0;    /* New estimate of the number of rows */
  2597   2639     int i;                      /* Loop counter */
  2598   2640   
  2599   2641     assert( p->aSample!=0 );
  2600   2642     for(i=0; rc==SQLITE_OK && i<pList->nExpr; i++){
  2601   2643       nEst = p->aiRowEst[0];
  2602   2644       rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst);
  2603   2645       nRowEst += nEst;
................................................................................
  2978   3020     u16 wctrlFlags                  /* Flags passed to sqlite3WhereBegin() */
  2979   3021   ){
  2980   3022     if( pParse->explain==2 ){
  2981   3023       struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
  2982   3024       Vdbe *v = pParse->pVdbe;      /* VM being constructed */
  2983   3025       sqlite3 *db = pParse->db;     /* Database handle */
  2984   3026       char *zMsg;                   /* Text to add to EQP output */
  2985         -    sqlite3_int64 nRow;           /* Expected number of rows visited by scan */
  2986   3027       int iId = pParse->iSelectId;  /* Select id (left-most output column) */
  2987   3028       int isSearch;                 /* True for a SEARCH. False for SCAN. */
  2988   3029       WhereLoop *pLoop;             /* The controlling WhereLoop object */
  2989   3030       u32 flags;                    /* Flags that describe this loop */
  2990   3031   
  2991   3032       pLoop = pLevel->pWLoop;
  2992   3033       flags = pLoop->wsFlags;
................................................................................
  3033   3074       }
  3034   3075   #ifndef SQLITE_OMIT_VIRTUALTABLE
  3035   3076       else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
  3036   3077         zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
  3037   3078                     pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
  3038   3079       }
  3039   3080   #endif
  3040         -    if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){
  3041         -      testcase( wctrlFlags & WHERE_ORDERBY_MIN );
  3042         -      nRow = 1;
  3043         -    }else{
  3044         -      nRow = (sqlite3_int64)pLoop->nOut;
  3045         -    }
  3046         -    zMsg = sqlite3MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow);
         3081  +    zMsg = sqlite3MAppendf(db, zMsg, "%s", zMsg);
  3047   3082       sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
  3048   3083     }
  3049   3084   }
  3050   3085   #else
  3051   3086   # define explainOneScan(u,v,w,x,y,z)
  3052   3087   #endif /* SQLITE_OMIT_EXPLAIN */
  3053   3088   
................................................................................
  3824   3859   }
  3825   3860   
  3826   3861   #ifdef WHERETRACE_ENABLED
  3827   3862   /*
  3828   3863   ** Print a WhereLoop object for debugging purposes
  3829   3864   */
  3830   3865   static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){
  3831         -  int nb = 2*((pTabList->nSrc+15)/16);
         3866  +  int nb = 1+(pTabList->nSrc+7)/8;
  3832   3867     struct SrcList_item *pItem = pTabList->a + p->iTab;
  3833   3868     Table *pTab = pItem->pTab;
  3834   3869     sqlite3DebugPrintf("%c %2d.%0*llx.%0*llx", p->cId,
  3835   3870                        p->iTab, nb, p->maskSelf, nb, p->prereq);
  3836   3871     sqlite3DebugPrintf(" %8s",
  3837   3872                        pItem->zAlias ? pItem->zAlias : pTab->zName);
  3838   3873     if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
................................................................................
  3856   3891       }else{
  3857   3892         z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
  3858   3893       }
  3859   3894       sqlite3DebugPrintf(" %-15s", z);
  3860   3895       sqlite3_free(z);
  3861   3896     }
  3862   3897     sqlite3DebugPrintf(" fg %05x N %d", p->wsFlags, p->nLTerm);
  3863         -  sqlite3DebugPrintf(" cost %.2g,%.2g,%.2g\n",
  3864         -                     p->prereq, p->rSetup, p->rRun, p->nOut);
         3898  +  sqlite3DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut);
  3865   3899   }
  3866   3900   #endif
  3867   3901   
  3868   3902   /*
  3869   3903   ** Convert bulk memory into a valid WhereLoop that can be passed
  3870   3904   ** to whereLoopClear harmlessly.
  3871   3905   */
................................................................................
  3991   4025     /* If pBuilder->pBest is defined, then only keep track of the single
  3992   4026     ** best WhereLoop.  pBuilder->pBest->maskSelf==0 indicates that no
  3993   4027     ** prior WhereLoops have been evaluated and that the current pTemplate
  3994   4028     ** is therefore the first and hence the best and should be retained.
  3995   4029     */
  3996   4030     if( (p = pBuilder->pBest)!=0 ){
  3997   4031       if( p->maskSelf!=0 ){
  3998         -      WhereCost rCost = p->rRun + p->rSetup;
  3999         -      WhereCost rTemplate = pTemplate->rRun + pTemplate->rSetup;
         4032  +      WhereCost rCost = whereCostAdd(p->rRun,p->rSetup);
         4033  +      WhereCost rTemplate = whereCostAdd(pTemplate->rRun,pTemplate->rSetup);
  4000   4034         if( rCost < rTemplate ){
  4001   4035           goto whereLoopInsert_noop;
  4002   4036         }
  4003   4037         if( rCost == rTemplate && p->prereq <= pTemplate->prereq ){
  4004   4038           goto whereLoopInsert_noop;
  4005   4039         }
  4006   4040       }
................................................................................
  4098   4132   ** If pProbe->tnum==0, that means pIndex is a fake index used for the
  4099   4133   ** INTEGER PRIMARY KEY.
  4100   4134   */
  4101   4135   static int whereLoopAddBtreeIndex(
  4102   4136     WhereLoopBuilder *pBuilder,     /* The WhereLoop factory */
  4103   4137     struct SrcList_item *pSrc,      /* FROM clause term being analyzed */
  4104   4138     Index *pProbe,                  /* An index on pSrc */
  4105         -  int nInMul                      /* Number of iterations due to IN */
         4139  +  WhereCost nInMul                /* log(Number of iterations due to IN) */
  4106   4140   ){
  4107   4141     WhereInfo *pWInfo = pBuilder->pWInfo;  /* WHERE analyse context */
  4108   4142     Parse *pParse = pWInfo->pParse;        /* Parsing context */
  4109   4143     sqlite3 *db = pParse->db;       /* Database connection malloc context */
  4110   4144     WhereLoop *pNew;                /* Template WhereLoop under construction */
  4111   4145     WhereTerm *pTerm;               /* A WhereTerm under consideration */
  4112   4146     int opMask;                     /* Valid operators for constraints */
................................................................................
  4114   4148     Bitmask saved_prereq;           /* Original value of pNew->prereq */
  4115   4149     u16 saved_nLTerm;               /* Original value of pNew->nLTerm */
  4116   4150     int saved_nEq;                  /* Original value of pNew->u.btree.nEq */
  4117   4151     u32 saved_wsFlags;              /* Original value of pNew->wsFlags */
  4118   4152     WhereCost saved_nOut;           /* Original value of pNew->nOut */
  4119   4153     int iCol;                       /* Index of the column in the table */
  4120   4154     int rc = SQLITE_OK;             /* Return code */
  4121         -  tRowcnt iRowEst;                /* Estimated index selectivity */
         4155  +  WhereCost nRowEst;              /* Estimated index selectivity */
  4122   4156     WhereCost rLogSize;             /* Logarithm of table size */
  4123   4157     WhereTerm *pTop, *pBtm;         /* Top and bottom range constraints */
  4124   4158   
  4125   4159     pNew = pBuilder->pNew;
  4126   4160     if( db->mallocFailed ) return SQLITE_NOMEM;
  4127   4161   
  4128   4162     assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
................................................................................
  4135   4169     }else{
  4136   4170       opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE;
  4137   4171     }
  4138   4172     if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
  4139   4173   
  4140   4174     if( pNew->u.btree.nEq < pProbe->nColumn ){
  4141   4175       iCol = pProbe->aiColumn[pNew->u.btree.nEq];
  4142         -    iRowEst = pProbe->aiRowEst[pNew->u.btree.nEq+1];
         4176  +    nRowEst = whereCostFromInt(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
  4143   4177     }else{
  4144   4178       iCol = -1;
  4145         -    iRowEst = 1;
         4179  +    nRowEst = 0;
  4146   4180     }
  4147   4181     pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol,
  4148   4182                           opMask, pProbe);
  4149   4183     saved_nEq = pNew->u.btree.nEq;
  4150   4184     saved_nLTerm = pNew->nLTerm;
  4151   4185     saved_wsFlags = pNew->wsFlags;
  4152   4186     saved_prereq = pNew->prereq;
  4153   4187     saved_nOut = pNew->nOut;
  4154         -  pNew->rSetup = (WhereCost)0;
  4155         -  rLogSize = estLog(pProbe->aiRowEst[0]);
         4188  +  pNew->rSetup = 0;
         4189  +  rLogSize = estLog(whereCostFromInt(pProbe->aiRowEst[0]));
  4156   4190     for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
  4157         -    int nIn = 1;
         4191  +    int nIn = 0;
  4158   4192       if( pTerm->prereqRight & pNew->maskSelf ) continue;
  4159   4193       pNew->wsFlags = saved_wsFlags;
  4160   4194       pNew->u.btree.nEq = saved_nEq;
  4161   4195       pNew->nLTerm = saved_nLTerm;
  4162   4196       if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
  4163   4197       pNew->aLTerm[pNew->nLTerm++] = pTerm;
  4164   4198       pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf;
  4165   4199       pNew->rRun = rLogSize;
  4166   4200       if( pTerm->eOperator & WO_IN ){
  4167   4201         Expr *pExpr = pTerm->pExpr;
  4168   4202         pNew->wsFlags |= WHERE_COLUMN_IN;
  4169   4203         if( ExprHasProperty(pExpr, EP_xIsSelect) ){
  4170   4204           /* "x IN (SELECT ...)":  Assume the SELECT returns 25 rows */
  4171         -        nIn = 25;
         4205  +        nIn = 46;  /* whereCostFromInt(25) */
  4172   4206         }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
  4173   4207           /* "x IN (value, value, ...)" */
  4174         -        nIn = pExpr->x.pList->nExpr;
         4208  +        nIn = whereCostFromInt(pExpr->x.pList->nExpr);
  4175   4209         }
  4176         -      pNew->rRun *= nIn;
         4210  +      pNew->rRun += nIn;
  4177   4211         pNew->u.btree.nEq++;
  4178         -      pNew->nOut = (WhereCost)iRowEst * nInMul * nIn;
         4212  +      pNew->nOut = nRowEst + nInMul + nIn;
  4179   4213       }else if( pTerm->eOperator & (WO_EQ) ){
  4180   4214         assert( (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0
  4181         -                  || nInMul==1 );
         4215  +                  || nInMul==0 );
  4182   4216         pNew->wsFlags |= WHERE_COLUMN_EQ;
  4183   4217         if( iCol<0  
  4184         -       || (pProbe->onError!=OE_None && nInMul==1
         4218  +       || (pProbe->onError!=OE_None && nInMul==0
  4185   4219              && pNew->u.btree.nEq==pProbe->nColumn-1)
  4186   4220         ){
  4187   4221           testcase( pNew->wsFlags & WHERE_COLUMN_IN );
  4188   4222           pNew->wsFlags |= WHERE_ONEROW;
  4189   4223         }
  4190   4224         pNew->u.btree.nEq++;
  4191         -      pNew->nOut = (WhereCost)iRowEst * nInMul;
         4225  +      pNew->nOut = nRowEst + nInMul;
  4192   4226       }else if( pTerm->eOperator & (WO_ISNULL) ){
  4193   4227         pNew->wsFlags |= WHERE_COLUMN_NULL;
  4194   4228         pNew->u.btree.nEq++;
  4195         -      nIn = 2;  /* Assume IS NULL matches two rows */
  4196         -      pNew->nOut = (WhereCost)iRowEst * nInMul * nIn;
         4229  +      nIn = 10;  /* Assume IS NULL matches two rows */
         4230  +      pNew->nOut = nRowEst + nInMul + nIn;
  4197   4231       }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
  4198   4232         pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
  4199   4233         pBtm = pTerm;
  4200   4234         pTop = 0;
  4201   4235       }else if( pTerm->eOperator & (WO_LT|WO_LE) ){
  4202   4236         pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
  4203   4237         pTop = pTerm;
................................................................................
  4205   4239                        pNew->aLTerm[pNew->nLTerm-2] : 0;
  4206   4240       }
  4207   4241       if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
  4208   4242         /* Adjust nOut and rRun for STAT3 range values */
  4209   4243         WhereCost rDiv;
  4210   4244         whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq,
  4211   4245                           pBtm, pTop, &rDiv);
  4212         -      pNew->nOut = saved_nOut/rDiv;
         4246  +      pNew->nOut = saved_nOut - rDiv;
  4213   4247       }
  4214   4248   #ifdef SQLITE_ENABLE_STAT3
  4215   4249       if( pNew->u.btree.nEq==1 && pProbe->nSample ){
         4250  +      tRowcnt nOut = 0;
  4216   4251         if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){
  4217         -        rc = whereEqualScanEst(pParse, pProbe, pTerm->pExpr->pRight,
  4218         -                               &pNew->nOut);
         4252  +        rc = whereEqualScanEst(pParse, pProbe, pTerm->pExpr->pRight, &nOut);
  4219   4253         }else if( (pTerm->eOperator & WO_IN)
  4220   4254                &&  !ExprHasProperty(pTerm->pExpr, EP_xIsSelect)  ){
  4221         -        rc = whereInScanEst(pParse, pProbe, pTerm->pExpr->x.pList,
  4222         -                             &pNew->nOut);
  4223         -
         4255  +        rc = whereInScanEst(pParse, pProbe, pTerm->pExpr->x.pList, &nOut);
  4224   4256         }
         4257  +      pNew->nOut = whereCostFromInt(nOut);
  4225   4258       }
  4226   4259   #endif
  4227   4260       if( pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK) ){
  4228         -      pNew->rRun += pNew->nOut;  /* Unit step cost to reach each row */
         4261  +      /* Step cost for each output row */
         4262  +      pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut);
  4229   4263       }else{
  4230   4264         /* Each row involves a step of the index, then a binary search of
  4231   4265         ** the main table */
  4232         -      pNew->rRun += pNew->nOut*(1 + rLogSize);
         4266  +      pNew->rRun = rLogSize>90 ? 
         4267  +                        whereCostAdd(pNew->rRun, pNew->nOut+rLogSize-90) :
         4268  +                        pNew->rRun;
  4233   4269       }
  4234   4270       /* TBD: Adjust nOut for additional constraints */
  4235   4271       rc = whereLoopInsert(pBuilder, pNew);
  4236   4272       if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
  4237   4273        && pNew->u.btree.nEq<=pProbe->nColumn
  4238   4274        && pProbe->zName!=0
  4239   4275       ){
  4240         -      whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul*nIn);
         4276  +      whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
  4241   4277       }
  4242   4278     }
  4243   4279     pNew->prereq = saved_prereq;
  4244   4280     pNew->u.btree.nEq = saved_nEq;
  4245   4281     pNew->wsFlags = saved_wsFlags;
  4246   4282     pNew->nOut = saved_nOut;
  4247   4283     pNew->nLTerm = saved_nLTerm;
................................................................................
  4343   4379       if( pSrc->notIndexed==0 ){
  4344   4380         /* The real indices of the table are only considered if the
  4345   4381         ** NOT INDEXED qualifier is omitted from the FROM clause */
  4346   4382         sPk.pNext = pFirst;
  4347   4383       }
  4348   4384       pProbe = &sPk;
  4349   4385     }
  4350         -  rSize = (WhereCost)pSrc->pTab->nRowEst;
         4386  +  rSize = whereCostFromInt(pSrc->pTab->nRowEst);
  4351   4387     rLogSize = estLog(rSize);
  4352   4388   
  4353   4389     /* Automatic indexes */
  4354   4390     if( !pBuilder->pBest
  4355   4391      && pTabList->nSrc>1
  4356   4392      && (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0 
  4357   4393      && !pSrc->viaCoroutine
................................................................................
  4365   4401       for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
  4366   4402         if( pTerm->prereqRight & pNew->maskSelf ) continue;
  4367   4403         if( termCanDriveIndex(pTerm, pSrc, 0) ){
  4368   4404           pNew->u.btree.nEq = 1;
  4369   4405           pNew->u.btree.pIndex = 0;
  4370   4406           pNew->nLTerm = 1;
  4371   4407           pNew->aLTerm[0] = pTerm;
  4372         -        pNew->rSetup = 20*rLogSize*pSrc->pTab->nRowEst;
  4373         -        pNew->nOut = (WhereCost)10;
  4374         -        pNew->rRun = rLogSize + pNew->nOut;
         4408  +        assert( 43==whereCostFromInt(20) );
         4409  +        pNew->rSetup = 43 + rLogSize + rSize;
         4410  +        pNew->nOut = 33;  assert( 33==whereCostFromInt(10) );
         4411  +        pNew->rRun = whereCostAdd(rLogSize,pNew->nOut);
  4375   4412           pNew->wsFlags = WHERE_TEMP_INDEX;
  4376   4413           pNew->prereq = mExtra | pTerm->prereqRight;
  4377   4414           rc = whereLoopInsert(pBuilder, pNew);
  4378   4415         }
  4379   4416       }
  4380   4417     }
  4381   4418   
  4382   4419     /* Loop over all indices
  4383   4420     */
  4384   4421     for(; rc==SQLITE_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){
  4385   4422       pNew->u.btree.nEq = 0;
  4386   4423       pNew->nLTerm = 0;
  4387   4424       pNew->iSortIdx = 0;
  4388         -    pNew->rSetup = (WhereCost)0;
         4425  +    pNew->rSetup = 0;
  4389   4426       pNew->prereq = mExtra;
  4390   4427       pNew->u.btree.pIndex = pProbe;
  4391   4428       b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor);
  4392   4429       if( pProbe->tnum<=0 ){
  4393   4430         /* Integer primary key index */
  4394   4431         pNew->wsFlags = WHERE_IPK;
  4395   4432   
  4396   4433         /* Full table scan */
  4397   4434         pNew->iSortIdx = b ? iSortIdx : 0;
  4398   4435         pNew->nOut = rSize;
  4399         -      pNew->rRun = (rSize + rLogSize)*(3+b); /* 4x penalty for a full-scan */
         4436  +      pNew->rRun = whereCostAdd(rSize,rLogSize) + 16 + b*4;
  4400   4437         rc = whereLoopInsert(pBuilder, pNew);
  4401   4438         if( rc ) break;
  4402   4439       }else{
  4403   4440         Bitmask m = pSrc->colUsed & ~columnsUsedByIndex(pProbe);
  4404   4441         pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
  4405   4442   
  4406   4443         /* Full scan via index */
................................................................................
  4408   4445          && pProbe->bUnordered==0
  4409   4446          && (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
  4410   4447          && sqlite3GlobalConfig.bUseCis
  4411   4448          && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
  4412   4449         ){
  4413   4450           pNew->iSortIdx = b ? iSortIdx : 0;
  4414   4451           pNew->nOut = rSize;
  4415         -        pNew->rRun = (m==0) ? (rSize + rLogSize)*(1+b) : (rSize*rLogSize);
         4452  +        pNew->rRun = whereCostAdd(rSize,rLogSize) + ((m==0 && b) ? 10 : 0);
  4416   4453           rc = whereLoopInsert(pBuilder, pNew);
  4417   4454           if( rc ) break;
  4418   4455         }
  4419   4456       }
  4420         -    rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 1);
         4457  +    rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
  4421   4458   
  4422   4459       /* If there was an INDEXED BY clause, then only that one index is
  4423   4460       ** considered. */
  4424   4461       if( pSrc->pIndex ) break;
  4425   4462     }
  4426   4463     return rc;
  4427   4464   }
................................................................................
  4563   4600         assert( pNew->nLTerm<=pNew->nLSlot );
  4564   4601         pNew->u.vtab.idxNum = pIdxInfo->idxNum;
  4565   4602         pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr;
  4566   4603         pIdxInfo->needToFreeIdxStr = 0;
  4567   4604         pNew->u.vtab.idxStr = pIdxInfo->idxStr;
  4568   4605         pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0)
  4569   4606                                        && pIdxInfo->orderByConsumed);
  4570         -      pNew->rSetup = (WhereCost)0;
  4571         -      pNew->rRun = pIdxInfo->estimatedCost;
  4572         -      pNew->nOut = (WhereCost)25;
         4607  +      pNew->rSetup = 0;
         4608  +      pNew->rRun = whereCostFromInt((tRowcnt)pIdxInfo->estimatedCost);
         4609  +      pNew->nOut = 46;  assert( 46 == whereCostFromInt(25) );
  4573   4610         whereLoopInsert(pBuilder, pNew);
  4574   4611         if( pNew->u.vtab.needFree ){
  4575   4612           sqlite3_free(pNew->u.vtab.idxStr);
  4576   4613           pNew->u.vtab.needFree = 0;
  4577   4614         }
  4578   4615       }
  4579   4616     }  
................................................................................
  4641   4678           sBest.rRun = 0;
  4642   4679           if( IsVirtual(pItem->pTab) ){
  4643   4680             rc = whereLoopAddVirtual(&sSubBuild, mExtra);
  4644   4681           }else{
  4645   4682             rc = whereLoopAddBtree(&sSubBuild, mExtra);
  4646   4683           }
  4647   4684           if( sBest.maskSelf==0 ) break;
  4648         -        assert( sBest.rSetup==(WhereCost)0 );
  4649         -        rTotal += sBest.rRun;
  4650         -        nRow += sBest.nOut;
         4685  +        assert( sBest.rSetup==0 );
         4686  +        rTotal = whereCostAdd(rTotal, sBest.rRun);
         4687  +        nRow = whereCostAdd(nRow, sBest.nOut);
  4651   4688           prereq |= sBest.prereq;
  4652   4689         }
  4653   4690         assert( pNew->nLSlot>=1 );
  4654   4691         pNew->nLTerm = 1;
  4655   4692         pNew->aLTerm[0] = pTerm;
  4656   4693         pNew->wsFlags = WHERE_MULTI_OR;
  4657         -      pNew->rSetup = (WhereCost)0;
         4694  +      pNew->rSetup = 0;
  4658   4695         pNew->rRun = rTotal;
  4659   4696         pNew->nOut = nRow;
  4660   4697         pNew->prereq = prereq;
  4661   4698         memset(&pNew->u, 0, sizeof(pNew->u));
  4662   4699         rc = whereLoopInsert(pBuilder, pNew);
  4663   4700         whereLoopClear(pWInfo->pParse->db, &sBest);
  4664   4701       }
................................................................................
  4675   4712     Bitmask mPrior = 0;
  4676   4713     int iTab;
  4677   4714     SrcList *pTabList = pWInfo->pTabList;
  4678   4715     struct SrcList_item *pItem;
  4679   4716     sqlite3 *db = pWInfo->pParse->db;
  4680   4717     int nTabList = pWInfo->nLevel;
  4681   4718     int rc = SQLITE_OK;
  4682         -  WhereLoop *pNew, sNew;
         4719  +  WhereLoop *pNew;
  4683   4720   
  4684   4721     /* Loop over the tables in the join, from left to right */
  4685         -  pBuilder->pNew = pNew = &sNew;
         4722  +  pNew = pBuilder->pNew;
  4686   4723     whereLoopInit(pNew);
  4687   4724     for(iTab=0, pItem=pTabList->a; iTab<nTabList; iTab++, pItem++){
  4688   4725       pNew->iTab = iTab;
  4689   4726       pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor);
  4690   4727       if( (pItem->jointype & (JT_LEFT|JT_CROSS))!=0 ){
  4691   4728         mExtra = mPrior;
  4692   4729       }
................................................................................
  4698   4735       if( rc==SQLITE_OK ){
  4699   4736         rc = whereLoopAddOr(pBuilder, mExtra);
  4700   4737       }
  4701   4738       mPrior |= pNew->maskSelf;
  4702   4739       if( rc || db->mallocFailed ) break;
  4703   4740     }
  4704   4741     whereLoopClear(db, pNew);
  4705         -  pBuilder->pNew = 0;
  4706   4742     return rc;
  4707   4743   }
  4708   4744   
  4709   4745   /*
  4710   4746   ** Examine a WherePath (with the addition of the extra WhereLoop of the 5th
  4711   4747   ** parameters) to see if it outputs rows in the requested ORDER BY
  4712   4748   ** (or GROUP BY) without requiring a separate source operation.  Return:
................................................................................
  4984   5020     memset(aFrom, 0, sizeof(aFrom[0]));
  4985   5021     pX = (WhereLoop**)(aFrom+mxChoice);
  4986   5022     for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){
  4987   5023       pFrom->aLoop = pX;
  4988   5024     }
  4989   5025   
  4990   5026     /* Seed the search with a single WherePath containing zero WhereLoops */
  4991         -  aFrom[0].nRow = (WhereCost)1;
         5027  +  aFrom[0].nRow = 0;
  4992   5028     nFrom = 1;
  4993   5029   
  4994   5030     /* Precompute the cost of sorting the final result set, if the caller
  4995   5031     ** to sqlite3WhereBegin() was concerned about sorting */
  4996         -  rSortCost = (WhereCost)0;
  4997         -  if( pWInfo->pOrderBy==0 || nRowEst<=0.0 ){
         5032  +  rSortCost = 0;
         5033  +  if( pWInfo->pOrderBy==0 || nRowEst==0 ){
  4998   5034       aFrom[0].isOrderedValid = 1;
  4999   5035     }else{
  5000   5036       /* Compute an estimate on the cost to sort the entire result set */
  5001         -    rSortCost = nRowEst*estLog(nRowEst);
         5037  +    rSortCost = nRowEst + estLog(nRowEst);
  5002   5038   #ifdef WHERETRACE_ENABLED
  5003   5039       if( sqlite3WhereTrace>=2 ){
  5004         -      sqlite3DebugPrintf("---- sort cost=%-7.2g\n", rSortCost);
         5040  +      sqlite3DebugPrintf("---- sort cost=%-3d\n", rSortCost);
  5005   5041       }
  5006   5042   #endif
  5007   5043     }
  5008   5044   
  5009   5045     /* Compute successively longer WherePaths using the previous generation
  5010   5046     ** of WherePaths as the basis for the next.  Keep track of the mxChoice
  5011   5047     ** best paths at each generation */
................................................................................
  5017   5053           Bitmask revMask = 0;
  5018   5054           u8 isOrderedValid = pFrom->isOrderedValid;
  5019   5055           u8 isOrdered = pFrom->isOrdered;
  5020   5056           if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
  5021   5057           if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
  5022   5058           /* At this point, pWLoop is a candidate to be the next loop. 
  5023   5059           ** Compute its cost */
  5024         -        rCost = pWLoop->rSetup + pWLoop->rRun*pFrom->nRow + pFrom->rCost;
         5060  +        rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
         5061  +        rCost = whereCostAdd(rCost, pFrom->rCost);
  5025   5062           maskNew = pFrom->maskLoop | pWLoop->maskSelf;
  5026   5063           if( !isOrderedValid ){
  5027   5064             switch( wherePathSatisfiesOrderBy(pWInfo, pFrom, iLoop, iLoop==nLoop-1,
  5028   5065                                               pWLoop, &revMask) ){
  5029   5066               case 1:  /* Yes.  pFrom+pWLoop does satisfy the ORDER BY clause */
  5030   5067                 isOrdered = 1;
  5031   5068                 isOrderedValid = 1;
  5032   5069                 break;
  5033   5070               case 0:  /* No.  pFrom+pWLoop will require a separate sort */
  5034   5071                 isOrdered = 0;
  5035   5072                 isOrderedValid = 1;
  5036         -              rCost += rSortCost;
         5073  +              rCost = whereCostAdd(rCost, rSortCost);
  5037   5074                 break;
  5038   5075               default: /* Cannot tell yet.  Try again on the next iteration */
  5039   5076                 break;
  5040   5077             }
  5041   5078           }else{
  5042   5079             revMask = pFrom->revLoop;
  5043   5080           }
................................................................................
  5047   5084               break;
  5048   5085             }
  5049   5086           }
  5050   5087           if( jj>=nTo ){
  5051   5088             if( nTo>=mxChoice && rCost>=mxCost ){
  5052   5089   #ifdef WHERETRACE_ENABLED
  5053   5090               if( sqlite3WhereTrace&0x4 ){
  5054         -              sqlite3DebugPrintf("Skip   %s cost=%-7.2g order=%c\n",
         5091  +              sqlite3DebugPrintf("Skip   %s cost=%3d order=%c\n",
  5055   5092                     wherePathName(pFrom, iLoop, pWLoop), rCost,
  5056   5093                     isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
  5057   5094               }
  5058   5095   #endif
  5059   5096               continue;
  5060   5097             }
  5061   5098             /* Add a new Path to the aTo[] set */
................................................................................
  5065   5102             }else{
  5066   5103               /* New path replaces the prior worst to keep count below mxChoice */
  5067   5104               for(jj=nTo-1; aTo[jj].rCost<mxCost; jj--){ assert(jj>0); }
  5068   5105             }
  5069   5106             pTo = &aTo[jj];
  5070   5107   #ifdef WHERETRACE_ENABLED
  5071   5108             if( sqlite3WhereTrace&0x4 ){
  5072         -            sqlite3DebugPrintf("New    %s cost=%-7.2g order=%c\n",
         5109  +            sqlite3DebugPrintf("New    %s cost=%-3d order=%c\n",
  5073   5110                   wherePathName(pFrom, iLoop, pWLoop), rCost,
  5074   5111                   isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
  5075   5112             }
  5076   5113   #endif
  5077   5114           }else{
  5078   5115             if( pTo->rCost<=rCost ){
  5079   5116   #ifdef WHERETRACE_ENABLED
  5080   5117               if( sqlite3WhereTrace&0x4 ){
  5081   5118                 sqlite3DebugPrintf(
  5082         -                  "Skip   %s cost=%-7.2g order=%c",
         5119  +                  "Skip   %s cost=%-3d order=%c",
  5083   5120                     wherePathName(pFrom, iLoop, pWLoop), rCost,
  5084   5121                     isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
  5085         -              sqlite3DebugPrintf("   vs %s cost=%-7.2g order=%c\n",
         5122  +              sqlite3DebugPrintf("   vs %s cost=%-3d order=%c\n",
  5086   5123                     wherePathName(pTo, iLoop+1, 0), pTo->rCost,
  5087   5124                     pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
  5088   5125               }
  5089   5126   #endif
  5090   5127               continue;
  5091   5128             }
  5092   5129             /* A new and better score for a previously created equivalent path */
  5093   5130   #ifdef WHERETRACE_ENABLED
  5094   5131             if( sqlite3WhereTrace&0x4 ){
  5095   5132               sqlite3DebugPrintf(
  5096         -                "Update %s cost=%-7.2g order=%c",
         5133  +                "Update %s cost=%-3d order=%c",
  5097   5134                   wherePathName(pFrom, iLoop, pWLoop), rCost,
  5098   5135                   isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?');
  5099         -            sqlite3DebugPrintf("  was %s cost=%-7.2g order=%c\n",
         5136  +            sqlite3DebugPrintf("  was %s cost=%-3d order=%c\n",
  5100   5137                   wherePathName(pTo, iLoop+1, 0), pTo->rCost,
  5101   5138                   pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
  5102   5139             }
  5103   5140   #endif
  5104   5141           }
  5105   5142           /* pWLoop is a winner.  Add it to the set of best so far */
  5106   5143           pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf;
  5107   5144           pTo->revLoop = revMask;
  5108         -        pTo->nRow = pFrom->nRow * pWLoop->nOut;
         5145  +        pTo->nRow = pFrom->nRow + pWLoop->nOut;
  5109   5146           pTo->rCost = rCost;
  5110   5147           pTo->isOrderedValid = isOrderedValid;
  5111   5148           pTo->isOrdered = isOrdered;
  5112   5149           memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop);
  5113   5150           pTo->aLoop[iLoop] = pWLoop;
  5114   5151           if( nTo>=mxChoice ){
  5115   5152             mxCost = aTo[0].rCost;
................................................................................
  5120   5157         }
  5121   5158       }
  5122   5159   
  5123   5160   #ifdef WHERETRACE_ENABLED
  5124   5161       if( sqlite3WhereTrace>=2 ){
  5125   5162         sqlite3DebugPrintf("---- after round %d ----\n", iLoop);
  5126   5163         for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){
  5127         -        sqlite3DebugPrintf(" %s cost=%-7.2g nrow=%-7.2g order=%c",
         5164  +        sqlite3DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c",
  5128   5165              wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
  5129   5166              pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?');
  5130   5167           if( pTo->isOrderedValid && pTo->isOrdered ){
  5131   5168             sqlite3DebugPrintf(" rev=0x%llx\n", pTo->revLoop);
  5132   5169           }else{
  5133   5170             sqlite3DebugPrintf("\n");
  5134   5171           }
................................................................................
  5180   5217   ** general-purpose query planner, and thereby yield faster sqlite3_prepare()
  5181   5218   ** times for the common case.
  5182   5219   **
  5183   5220   ** Return non-zero on success, if this query can be handled by this
  5184   5221   ** no-frills query planner.  Return zero if this query needs the 
  5185   5222   ** general-purpose query planner.
  5186   5223   */
  5187         -static int whereSimpleFastCase(WhereLoopBuilder *pBuilder){
         5224  +static int whereShortCut(WhereLoopBuilder *pBuilder){
  5188   5225     WhereInfo *pWInfo;
  5189   5226     struct SrcList_item *pItem;
  5190   5227     WhereClause *pWC;
  5191   5228     WhereTerm *pTerm;
  5192   5229     WhereLoop *pLoop;
  5193   5230     int iCur;
  5194   5231     int j;
................................................................................
  5207   5244     pLoop->wsFlags = 0;
  5208   5245     pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0);
  5209   5246     if( pTerm ){
  5210   5247       pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
  5211   5248       pLoop->aLTerm[0] = pTerm;
  5212   5249       pLoop->nLTerm = 1;
  5213   5250       pLoop->u.btree.nEq = 1;
  5214         -    pLoop->rRun = (WhereCost)10;
         5251  +    pLoop->rRun = 33;  /* 33 == whereCostFromInt(10) */
  5215   5252     }else{
  5216   5253       for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
  5217   5254         if( pIdx->onError==OE_None ) continue;
  5218   5255         for(j=0; j<pIdx->nColumn; j++){
  5219   5256           pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx);
  5220   5257           if( pTerm==0 ) break;
  5221   5258           whereLoopResize(pWInfo->pParse->db, pLoop, j);
................................................................................
  5225   5262         pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED;
  5226   5263         if( (pItem->colUsed & ~columnsUsedByIndex(pIdx))==0 ){
  5227   5264           pLoop->wsFlags |= WHERE_IDX_ONLY;
  5228   5265         }
  5229   5266         pLoop->nLTerm = j;
  5230   5267         pLoop->u.btree.nEq = j;
  5231   5268         pLoop->u.btree.pIndex = pIdx;
  5232         -      pLoop->rRun = (WhereCost)15;
         5269  +      pLoop->rRun = 39;  /* 39 == whereCostFromInt(15) */
  5233   5270         break;
  5234   5271       }
  5235   5272     }
  5236   5273     if( pLoop->wsFlags ){
  5237   5274       pLoop->nOut = (WhereCost)1;
  5238   5275       pWInfo->a[0].pWLoop = pLoop;
  5239   5276       pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur);
................................................................................
  5402   5439     pWInfo->wctrlFlags = wctrlFlags;
  5403   5440     pWInfo->savedNQueryLoop = pParse->nQueryLoop;
  5404   5441     pMaskSet = &pWInfo->sMaskSet;
  5405   5442     sWLB.pWInfo = pWInfo;
  5406   5443     sWLB.pWC = &pWInfo->sWC;
  5407   5444     sWLB.pNew = (WhereLoop*)&pWInfo->a[nTabList];
  5408   5445     whereLoopInit(sWLB.pNew);
         5446  +#ifdef SQLITE_DEBUG
         5447  +  sWLB.pNew->cId = '*';
         5448  +#endif
  5409   5449   
  5410   5450     /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
  5411   5451     ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
  5412   5452     if( OptimizationDisabled(db, SQLITE_DistinctOpt) ) pDistinct = 0;
  5413   5453   
  5414   5454     /* Split the WHERE clause into separate subexpressions where each
  5415   5455     ** subexpression is separated by an AND operator.
................................................................................
  5474   5514     if( pDistinct && isDistinctRedundant(pParse,pTabList,&pWInfo->sWC,pDistinct) ){
  5475   5515       pDistinct = 0;
  5476   5516       pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
  5477   5517     }
  5478   5518   
  5479   5519     /* Construct the WhereLoop objects */
  5480   5520     WHERETRACE(("*** Optimizer Start ***\n"));
  5481         -  if( nTabList!=1 || whereSimpleFastCase(&sWLB)==0 ){
         5521  +  if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
  5482   5522       rc = whereLoopAddAll(&sWLB);
  5483   5523       if( rc ) goto whereBeginError;
  5484   5524     
  5485   5525       /* Display all of the WhereLoop objects if wheretrace is enabled */
  5486   5526   #ifdef WHERETRACE_ENABLED
  5487   5527       if( sqlite3WhereTrace ){
  5488   5528         WhereLoop *p;