/ Check-in [b9d41c34]
Login

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

Overview
Comment:Allow the sqlite_stat2 table to contain a number of samples other than the default of 10.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | query-planner-tweaks
Files: files | file ages | folders
SHA1: b9d41c3490bf325915227a32b612e6772fb62fa9
User & Date: drh 2011-08-05 01:09:49
Context
2011-08-06
02:03
Merge together the fork in the query-planner-tweaks branch. check-in: 2daab6bd user: drh tags: query-planner-tweaks
2011-08-05
01:09
Allow the sqlite_stat2 table to contain a number of samples other than the default of 10. check-in: b9d41c34 user: drh tags: query-planner-tweaks
2011-08-03
01:07
Adjust the output row estimating logic when using STAT2. check-in: c8ba8855 user: drh tags: query-planner-tweaks
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/analyze.c.

   560    560   ** If the Index.aSample variable is not NULL, delete the aSample[] array
   561    561   ** and its contents.
   562    562   */
   563    563   void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
   564    564   #ifdef SQLITE_ENABLE_STAT2
   565    565     if( pIdx->aSample ){
   566    566       int j;
   567         -    for(j=0; j<SQLITE_INDEX_SAMPLES; j++){
          567  +    for(j=0; j<pIdx->nSample; j++){
   568    568         IndexSample *p = &pIdx->aSample[j];
   569    569         if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){
   570    570           sqlite3DbFree(db, p->u.z);
   571    571         }
   572    572       }
   573    573       sqlite3DbFree(db, pIdx->aSample);
   574    574     }
................................................................................
   610    610     /* Clear any prior statistics */
   611    611     assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   612    612     for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
   613    613       Index *pIdx = sqliteHashData(i);
   614    614       sqlite3DefaultRowEst(pIdx);
   615    615       sqlite3DeleteIndexSamples(db, pIdx);
   616    616       pIdx->aSample = 0;
          617  +    pIdx->nSample = 0;
   617    618     }
   618    619   
   619    620     /* Check to make sure the sqlite_stat1 table exists */
   620    621     sInfo.db = db;
   621    622     sInfo.zDatabase = db->aDb[iDb].zName;
   622    623     if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
   623    624       return SQLITE_ERROR;
................................................................................
   639    640     if( rc==SQLITE_OK && !sqlite3FindTable(db, "sqlite_stat2", sInfo.zDatabase) ){
   640    641       rc = SQLITE_ERROR;
   641    642     }
   642    643     if( rc==SQLITE_OK ){
   643    644       sqlite3_stmt *pStmt = 0;
   644    645   
   645    646       zSql = sqlite3MPrintf(db, 
   646         -        "SELECT idx,sampleno,sample FROM %Q.sqlite_stat2", sInfo.zDatabase);
          647  +        "SELECT idx, sampleno, sample FROM %Q.sqlite_stat2"
          648  +        " ORDER BY rowid DESC", sInfo.zDatabase);
   647    649       if( !zSql ){
   648    650         rc = SQLITE_NOMEM;
   649    651       }else{
   650    652         rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
   651    653         sqlite3DbFree(db, zSql);
   652    654       }
   653    655   
   654    656       if( rc==SQLITE_OK ){
   655    657         while( sqlite3_step(pStmt)==SQLITE_ROW ){
   656    658           char *zIndex;   /* Index name */
   657    659           Index *pIdx;    /* Pointer to the index object */
          660  +        int iSample;
          661  +        int eType;
          662  +        IndexSample *pSample;
   658    663   
   659    664           zIndex = (char *)sqlite3_column_text(pStmt, 0);
   660         -        pIdx = zIndex ? sqlite3FindIndex(db, zIndex, sInfo.zDatabase) : 0;
   661         -        if( pIdx ){
   662         -          int iSample = sqlite3_column_int(pStmt, 1);
   663         -          if( iSample<SQLITE_INDEX_SAMPLES && iSample>=0 ){
   664         -            int eType = sqlite3_column_type(pStmt, 2);
   665         -
   666         -            if( pIdx->aSample==0 ){
   667         -              static const int sz = sizeof(IndexSample)*SQLITE_INDEX_SAMPLES;
   668         -              pIdx->aSample = (IndexSample *)sqlite3DbMallocRaw(0, sz);
   669         -              if( pIdx->aSample==0 ){
   670         -                db->mallocFailed = 1;
   671         -                break;
   672         -              }
   673         -	      memset(pIdx->aSample, 0, sz);
   674         -            }
   675         -
   676         -            assert( pIdx->aSample );
   677         -            {
   678         -              IndexSample *pSample = &pIdx->aSample[iSample];
   679         -              pSample->eType = (u8)eType;
   680         -              if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
   681         -                pSample->u.r = sqlite3_column_double(pStmt, 2);
   682         -              }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
   683         -                const char *z = (const char *)(
   684         -                    (eType==SQLITE_BLOB) ?
   685         -                    sqlite3_column_blob(pStmt, 2):
   686         -                    sqlite3_column_text(pStmt, 2)
   687         -                );
   688         -                int n = sqlite3_column_bytes(pStmt, 2);
   689         -                if( n>24 ){
   690         -                  n = 24;
   691         -                }
   692         -                pSample->nByte = (u8)n;
   693         -                if( n < 1){
   694         -                  pSample->u.z = 0;
   695         -                }else{
   696         -                  pSample->u.z = sqlite3DbStrNDup(0, z, n);
   697         -                  if( pSample->u.z==0 ){
   698         -                    db->mallocFailed = 1;
   699         -                    break;
   700         -                  }
   701         -                }
   702         -              }
          665  +        if( zIndex==0 ) continue;
          666  +        pIdx = sqlite3FindIndex(db, zIndex, sInfo.zDatabase);
          667  +        if( pIdx==0 ) continue;
          668  +        iSample = sqlite3_column_int(pStmt, 1);
          669  +        if( iSample>=SQLITE_MAX_SAMPLES || iSample<0 ) continue;
          670  +        if( pIdx->nSample<=iSample ){
          671  +          IndexSample *pNew;
          672  +          int sz = sizeof(IndexSample)*(iSample+1);
          673  +          pNew = (IndexSample*)sqlite3Realloc(pIdx->aSample, sz);
          674  +          if( pNew==0 ){
          675  +            db->mallocFailed = 1;
          676  +            break;
          677  +          }
          678  +          pIdx->aSample = pNew;
          679  +          pIdx->nSample = iSample+1;
          680  +        }
          681  +        eType = sqlite3_column_type(pStmt, 2);
          682  +        pSample = &pIdx->aSample[iSample];
          683  +        pSample->eType = (u8)eType;
          684  +        if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
          685  +          pSample->u.r = sqlite3_column_double(pStmt, 2);
          686  +        }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){
          687  +          const char *z = (const char *)(
          688  +             (eType==SQLITE_BLOB) ?
          689  +              sqlite3_column_blob(pStmt, 2):
          690  +              sqlite3_column_text(pStmt, 2)
          691  +          );
          692  +          int n = sqlite3_column_bytes(pStmt, 2);
          693  +          if( n>24 ) n = 24;
          694  +          pSample->nByte = (u8)n;
          695  +          if( n < 1){
          696  +            pSample->u.z = 0;
          697  +          }else{
          698  +            pSample->u.z = sqlite3DbStrNDup(0, z, n);
          699  +            if( pSample->u.z==0 ){
          700  +              db->mallocFailed = 1;
          701  +              break;
   703    702               }
   704    703             }
   705    704           }
   706    705         }
   707    706         rc = sqlite3_finalize(pStmt);
   708    707       }
   709    708     }

Changes to src/sqliteInt.h.

    80     80   ** The number of samples of an index that SQLite takes in order to 
    81     81   ** construct a histogram of the table content when running ANALYZE
    82     82   ** and with SQLITE_ENABLE_STAT2
    83     83   */
    84     84   #ifndef SQLITE_INDEX_SAMPLES
    85     85   # define SQLITE_INDEX_SAMPLES 10
    86     86   #endif
           87  +#define SQLITE_MAX_SAMPLES 100
    87     88   
    88     89   /*
    89     90   ** The following macros are used to cast pointers to integers and
    90     91   ** integers to pointers.  The way you do this varies from one compiler
    91     92   ** to the next, so we have developed the following set of #if statements
    92     93   ** to generate appropriate macros for a wide range of compilers.
    93     94   **
................................................................................
  1481   1482     int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  1482   1483     unsigned *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
  1483   1484     Table *pTable;   /* The SQL table being indexed */
  1484   1485     int tnum;        /* Page containing root of this index in database file */
  1485   1486     u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  1486   1487     u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
  1487   1488     u8 bUnordered;   /* Use this index for == or IN queries only */
         1489  +  u8 nSample;      /* Number of slots in aSample[] */
  1488   1490     char *zColAff;   /* String defining the affinity of each column */
  1489   1491     Index *pNext;    /* The next index associated with the same table */
  1490   1492     Schema *pSchema; /* Schema containing this index */
  1491   1493     u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
  1492   1494     char **azColl;   /* Array of collation sequence names for index */
  1493   1495     IndexSample *aSample;    /* Array of SQLITE_INDEX_SAMPLES samples */
  1494   1496   };

Changes to src/where.c.

  2418   2418     */
  2419   2419     bestOrClauseIndex(pParse, pWC, pSrc, notReady, notValid, pOrderBy, pCost);
  2420   2420   }
  2421   2421   #endif /* SQLITE_OMIT_VIRTUALTABLE */
  2422   2422   
  2423   2423   /*
  2424   2424   ** Argument pIdx is a pointer to an index structure that has an array of
  2425         -** SQLITE_INDEX_SAMPLES evenly spaced samples of the first indexed column
         2425  +** pIdx->nSample evenly spaced samples of the first indexed column
  2426   2426   ** stored in Index.aSample. These samples divide the domain of values stored
  2427         -** the index into (SQLITE_INDEX_SAMPLES+1) regions.
         2427  +** the index into (pIdx->nSample+1) regions.
  2428   2428   ** Region 0 contains all values less than the first sample value. Region
  2429   2429   ** 1 contains values between the first and second samples.  Region 2 contains
  2430         -** values between samples 2 and 3.  And so on.  Region SQLITE_INDEX_SAMPLES
         2430  +** values between samples 2 and 3.  And so on.  Region pIdx->nSample
  2431   2431   ** contains values larger than the last sample.
  2432   2432   **
  2433   2433   ** If the index contains many duplicates of a single value, then it is
  2434   2434   ** possible that two or more adjacent samples can hold the same value.
  2435   2435   ** When that is the case, the smallest possible region code is returned
  2436   2436   ** when roundUp is false and the largest possible region code is returned
  2437   2437   ** when roundUp is true.
  2438   2438   **
  2439   2439   ** If successful, this function determines which of the regions value 
  2440   2440   ** pVal lies in, sets *piRegion to the region index (a value between 0
  2441         -** and SQLITE_INDEX_SAMPLES+1, inclusive) and returns SQLITE_OK.
         2441  +** and S+1, inclusive) and returns SQLITE_OK.
  2442   2442   ** Or, if an OOM occurs while converting text values between encodings,
  2443   2443   ** SQLITE_NOMEM is returned and *piRegion is undefined.
  2444   2444   */
  2445   2445   #ifdef SQLITE_ENABLE_STAT2
  2446   2446   static int whereRangeRegion(
  2447   2447     Parse *pParse,              /* Database connection */
  2448   2448     Index *pIdx,                /* Index to consider domain of */
................................................................................
  2449   2449     sqlite3_value *pVal,        /* Value to consider */
  2450   2450     int roundUp,                /* Return largest valid region if true */
  2451   2451     int *piRegion               /* OUT: Region of domain in which value lies */
  2452   2452   ){
  2453   2453     assert( roundUp==0 || roundUp==1 );
  2454   2454     if( ALWAYS(pVal) ){
  2455   2455       IndexSample *aSample = pIdx->aSample;
         2456  +    int nSample = pIdx->nSample;
  2456   2457       int i = 0;
  2457   2458       int eType = sqlite3_value_type(pVal);
  2458   2459   
         2460  +    assert( nSample>0 );
  2459   2461       if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
  2460   2462         double r = sqlite3_value_double(pVal);
  2461         -      for(i=0; i<SQLITE_INDEX_SAMPLES; i++){
         2463  +      for(i=0; i<nSample; i++){
  2462   2464           if( aSample[i].eType==SQLITE_NULL ) continue;
  2463   2465           if( aSample[i].eType>=SQLITE_TEXT ) break;
  2464   2466           if( roundUp ){
  2465   2467             if( aSample[i].u.r>r ) break;
  2466   2468           }else{
  2467   2469             if( aSample[i].u.r>=r ) break;
  2468   2470           }
  2469   2471         }
  2470   2472       }else if( eType==SQLITE_NULL ){
  2471   2473         i = 0;
  2472   2474         if( roundUp ){
  2473         -        while( i<SQLITE_INDEX_SAMPLES && aSample[i].eType==SQLITE_NULL ) i++;
         2475  +        while( i<nSample && aSample[i].eType==SQLITE_NULL ) i++;
  2474   2476         }
  2475   2477       }else{ 
  2476   2478         sqlite3 *db = pParse->db;
  2477   2479         CollSeq *pColl;
  2478   2480         const u8 *z;
  2479   2481         int n;
  2480   2482   
................................................................................
  2496   2498           if( !z ){
  2497   2499             return SQLITE_NOMEM;
  2498   2500           }
  2499   2501           assert( z && pColl && pColl->xCmp );
  2500   2502         }
  2501   2503         n = sqlite3ValueBytes(pVal, pColl->enc);
  2502   2504   
  2503         -      for(i=0; i<SQLITE_INDEX_SAMPLES; i++){
         2505  +      for(i=0; i<nSample; i++){
  2504   2506           int c;
  2505   2507           int eSampletype = aSample[i].eType;
  2506   2508           if( eSampletype==SQLITE_NULL || eSampletype<eType ) continue;
  2507   2509           if( (eSampletype!=eType) ) break;
  2508   2510   #ifndef SQLITE_OMIT_UTF16
  2509   2511           if( pColl->enc!=SQLITE_UTF8 ){
  2510   2512             int nSample;
................................................................................
  2522   2524           {
  2523   2525             c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z);
  2524   2526           }
  2525   2527           if( c-roundUp>=0 ) break;
  2526   2528         }
  2527   2529       }
  2528   2530   
  2529         -    assert( i>=0 && i<=SQLITE_INDEX_SAMPLES );
         2531  +    assert( i>=0 && i<=pIdx->nSample );
  2530   2532       *piRegion = i;
  2531   2533     }
  2532   2534     return SQLITE_OK;
  2533   2535   }
  2534   2536   #endif   /* #ifdef SQLITE_ENABLE_STAT2 */
  2535   2537   
  2536   2538   /*
................................................................................
  2622   2624   #ifdef SQLITE_ENABLE_STAT2
  2623   2625   
  2624   2626     if( nEq==0 && p->aSample ){
  2625   2627       sqlite3_value *pLowerVal = 0;
  2626   2628       sqlite3_value *pUpperVal = 0;
  2627   2629       int iEst;
  2628   2630       int iLower = 0;
  2629         -    int iUpper = SQLITE_INDEX_SAMPLES;
         2631  +    int nSample = p->nSample;
         2632  +    int iUpper = p->nSample;
  2630   2633       int roundUpUpper = 0;
  2631   2634       int roundUpLower = 0;
  2632   2635       u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
  2633   2636   
  2634   2637       if( pLower ){
  2635   2638         Expr *pExpr = pLower->pExpr->pRight;
  2636   2639         rc = valueFromExpr(pParse, pExpr, aff, &pLowerVal);
................................................................................
  2649   2652         sqlite3ValueFree(pUpperVal);
  2650   2653         goto range_est_fallback;
  2651   2654       }else if( pLowerVal==0 ){
  2652   2655         rc = whereRangeRegion(pParse, p, pUpperVal, roundUpUpper, &iUpper);
  2653   2656         if( pLower ) iLower = iUpper/2;
  2654   2657       }else if( pUpperVal==0 ){
  2655   2658         rc = whereRangeRegion(pParse, p, pLowerVal, roundUpLower, &iLower);
  2656         -      if( pUpper ) iUpper = (iLower + SQLITE_INDEX_SAMPLES + 1)/2;
         2659  +      if( pUpper ) iUpper = (iLower + p->nSample + 1)/2;
  2657   2660       }else{
  2658   2661         rc = whereRangeRegion(pParse, p, pUpperVal, roundUpUpper, &iUpper);
  2659   2662         if( rc==SQLITE_OK ){
  2660   2663           rc = whereRangeRegion(pParse, p, pLowerVal, roundUpLower, &iLower);
  2661   2664         }
  2662   2665       }
  2663   2666       WHERETRACE(("range scan regions: %d..%d\n", iLower, iUpper));
  2664   2667   
  2665   2668       iEst = iUpper - iLower;
  2666         -    testcase( iEst==SQLITE_INDEX_SAMPLES );
  2667         -    assert( iEst<=SQLITE_INDEX_SAMPLES );
         2669  +    testcase( iEst==nSample );
         2670  +    assert( iEst<=nSample );
         2671  +    assert( nSample>0 );
  2668   2672       if( iEst<1 ){
  2669         -      *piEst = 50/SQLITE_INDEX_SAMPLES;
         2673  +      *piEst = 50/nSample;
  2670   2674       }else{
  2671         -      *piEst = (iEst*100)/SQLITE_INDEX_SAMPLES;
         2675  +      *piEst = (iEst*100)/nSample;
  2672   2676       }
  2673   2677       sqlite3ValueFree(pLowerVal);
  2674   2678       sqlite3ValueFree(pUpperVal);
  2675   2679       return rc;
  2676   2680     }
  2677   2681   range_est_fallback:
  2678   2682   #else
................................................................................
  2714   2718     sqlite3_value *pRhs = 0;  /* VALUE on right-hand side of pTerm */
  2715   2719     int iLower, iUpper;       /* Range of histogram regions containing pRhs */
  2716   2720     u8 aff;                   /* Column affinity */
  2717   2721     int rc;                   /* Subfunction return code */
  2718   2722     double nRowEst;           /* New estimate of the number of rows */
  2719   2723   
  2720   2724     assert( p->aSample!=0 );
         2725  +  assert( p->nSample>0 );
  2721   2726     aff = p->pTable->aCol[p->aiColumn[0]].affinity;
  2722   2727     if( pExpr ){
  2723   2728       rc = valueFromExpr(pParse, pExpr, aff, &pRhs);
  2724   2729       if( rc ) goto whereEqualScanEst_cancel;
  2725   2730     }else{
  2726   2731       pRhs = sqlite3ValueNew(pParse->db);
  2727   2732     }
................................................................................
  2728   2733     if( pRhs==0 ) return SQLITE_NOTFOUND;
  2729   2734     rc = whereRangeRegion(pParse, p, pRhs, 0, &iLower);
  2730   2735     if( rc ) goto whereEqualScanEst_cancel;
  2731   2736     rc = whereRangeRegion(pParse, p, pRhs, 1, &iUpper);
  2732   2737     if( rc ) goto whereEqualScanEst_cancel;
  2733   2738     WHERETRACE(("equality scan regions: %d..%d\n", iLower, iUpper));
  2734   2739     if( iLower>=iUpper ){
  2735         -    nRowEst = p->aiRowEst[0]/(SQLITE_INDEX_SAMPLES*3);
         2740  +    nRowEst = p->aiRowEst[0]/(p->nSample*3);
  2736   2741       if( nRowEst<*pnRow ) *pnRow = nRowEst;
  2737   2742     }else{
  2738         -    nRowEst = (iUpper-iLower)*p->aiRowEst[0]/SQLITE_INDEX_SAMPLES;
         2743  +    nRowEst = (iUpper-iLower)*p->aiRowEst[0]/p->nSample;
  2739   2744       *pnRow = nRowEst;
  2740   2745     }
  2741   2746   
  2742   2747   whereEqualScanEst_cancel:
  2743   2748     sqlite3ValueFree(pRhs);
  2744   2749     return rc;
  2745   2750   }
................................................................................
  2772   2777     int iLower, iUpper;       /* Range of histogram regions containing pRhs */
  2773   2778     u8 aff;                   /* Column affinity */
  2774   2779     int rc = SQLITE_OK;       /* Subfunction return code */
  2775   2780     double nRowEst;           /* New estimate of the number of rows */
  2776   2781     int nSpan = 0;            /* Number of histogram regions spanned */
  2777   2782     int nSingle = 0;          /* Histogram regions hit by a single value */
  2778   2783     int nNotFound = 0;        /* Count of values that are not constants */
  2779         -  int i;                               /* Loop counter */
  2780         -  u8 aSpan[SQLITE_INDEX_SAMPLES+1];    /* Histogram regions that are spanned */
  2781         -  u8 aSingle[SQLITE_INDEX_SAMPLES+1];  /* Histogram regions hit once */
         2784  +  int i;                             /* Loop counter */
         2785  +  int nSample = p->nSample;          /* Number of samples */
         2786  +  u8 aSpan[SQLITE_MAX_SAMPLES+1];    /* Histogram regions that are spanned */
         2787  +  u8 aSingle[SQLITE_MAX_SAMPLES+1];  /* Histogram regions hit once */
  2782   2788   
  2783   2789     assert( p->aSample!=0 );
         2790  +  assert( nSample>0 );
  2784   2791     aff = p->pTable->aCol[p->aiColumn[0]].affinity;
  2785         -  memset(aSpan, 0, sizeof(aSpan));
  2786         -  memset(aSingle, 0, sizeof(aSingle));
         2792  +  memset(aSpan, 0, nSample+1);
         2793  +  memset(aSingle, 0, nSample+1);
  2787   2794     for(i=0; i<pList->nExpr; i++){
  2788   2795       sqlite3ValueFree(pVal);
  2789   2796       rc = valueFromExpr(pParse, pList->a[i].pExpr, aff, &pVal);
  2790   2797       if( rc ) break;
  2791   2798       if( pVal==0 || sqlite3_value_type(pVal)==SQLITE_NULL ){
  2792   2799         nNotFound++;
  2793   2800         continue;
................................................................................
  2795   2802       rc = whereRangeRegion(pParse, p, pVal, 0, &iLower);
  2796   2803       if( rc ) break;
  2797   2804       rc = whereRangeRegion(pParse, p, pVal, 1, &iUpper);
  2798   2805       if( rc ) break;
  2799   2806       if( iLower>=iUpper ){
  2800   2807         aSingle[iLower] = 1;
  2801   2808       }else{
  2802         -      assert( iLower>=0 && iUpper<=SQLITE_INDEX_SAMPLES );
         2809  +      assert( iLower>=0 && iUpper<=nSample );
  2803   2810         while( iLower<iUpper ) aSpan[iLower++] = 1;
  2804   2811       }
  2805   2812     }
  2806   2813     if( rc==SQLITE_OK ){
  2807         -    for(i=nSpan=0; i<=SQLITE_INDEX_SAMPLES; i++){
         2814  +    for(i=nSpan=0; i<=nSample; i++){
  2808   2815         if( aSpan[i] ){
  2809   2816           nSpan++;
  2810   2817         }else if( aSingle[i] ){
  2811   2818           nSingle++;
  2812   2819         }
  2813   2820       }
  2814         -    nRowEst = (nSpan*3+nSingle)*p->aiRowEst[0]/(3*SQLITE_INDEX_SAMPLES)
         2821  +    nRowEst = (nSpan*3+nSingle)*p->aiRowEst[0]/(3*nSample)
  2815   2822                  + nNotFound*p->aiRowEst[1];
  2816   2823       if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
  2817   2824       *pnRow = nRowEst;
  2818   2825       WHERETRACE(("IN row estimate: nSpan=%d, nSingle=%d, nNotFound=%d, est=%g\n",
  2819   2826                    nSpan, nSingle, nNotFound, nRowEst));
  2820   2827     }
  2821   2828     sqlite3ValueFree(pVal);