]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Further testing and bug fixing for sqlite_stat3. Added the Index.avgEq
authordrh <drh@noemail.net>
Sat, 13 Aug 2011 19:35:19 +0000 (19:35 +0000)
committerdrh <drh@noemail.net>
Sat, 13 Aug 2011 19:35:19 +0000 (19:35 +0000)
field to index statistics.  Fixed several problems in the query planner
associated with stat3.

FossilOrigin-Name: 89b2f70884cad0abdf4c66cb64ecddb2820ded74

13 files changed:
manifest
manifest.uuid
src/analyze.c
src/build.c
src/sqliteInt.h
src/where.c
test/analyze.test
test/analyze3.test
test/analyze5.test
test/analyze7.test
test/dbstatus.test
test/stat3.test
test/unordered.test

index 1e5050812e099ebc0e81e5c38862f2ce156ca113..635de7d9bffe137716063c3ddf4957e9015db409 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sthe\ssqlite_stat3.nDLT\sfield.\s\sUse\san\slinear\scongruence\sPRNG\sto\schoose\nwhich\ssamples\sto\sselect\sfrom\samong\sthose\swith\sthe\ssame\snEq\sfield.
-D 2011-08-13T15:25:10.607
+C Further\stesting\sand\sbug\sfixing\sfor\ssqlite_stat3.\s\sAdded\sthe\sIndex.avgEq\nfield\sto\sindex\sstatistics.\s\sFixed\sseveral\sproblems\sin\sthe\squery\splanner\nassociated\swith\sstat3.
+D 2011-08-13T19:35:19.088
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 1e6988b3c11dee9bd5edc0c804bd4468d74a9cdc
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -118,7 +118,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
 F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
 F src/alter.c ac80a0f31189f8b4a524ebf661e47e84536ee7f5
-F src/analyze.c 6901cc6e91cc6d4a6b584025f58ec2839783b6c3
+F src/analyze.c c04d95f4dc82b94250c4053ca36cc52b42f257ea
 F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
 F src/backup.c 986c15232757f2873dff35ee3b35cbf935fc573c
@@ -127,7 +127,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
 F src/btree.c 8c46f0ab69ad9549c75a3a91fed87abdaa743e2f
 F src/btree.h f5d775cd6cfc7ac32a2535b70e8d2af48ef5f2ce
 F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
-F src/build.c 4165efa323b4d3678a6b39fddb775627c18e9a80
+F src/build.c cd77ae979219d6363234b506de28c71f217063e1
 F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
 F src/ctime.c 0df87f944b17c17c6b3976a9758d8af2802e1b19
@@ -183,7 +183,7 @@ F src/select.c d219c4b68d603cc734b6f9b1e2780fee12a1fa0d
 F src/shell.c bbe7818ff5bc8614105ceb81ad67b8bdc0b671dd
 F src/sqlite.h.in e8eb090406b9a743befff4c387aa3bd5eeae661e
 F src/sqlite3ext.h 1a1a4f784aa9c3b00edd287940197de52487cd93
-F src/sqliteInt.h a4c0124ff6dbbf325002b4a34248cc08453c9739
+F src/sqliteInt.h f491be51e47267ae1454317fbd3438382e60fdb3
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 7ac64842c86cec2fc1a1d0e5c16d3beb8ad332bf
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -250,7 +250,7 @@ F src/vtab.c 901791a47318c0562cd0c676a2c6ff1bc530e582
 F src/wal.c 3154756177d6219e233d84291d5b05f4e06ff5e9
 F src/wal.h 66b40bd91bc29a5be1c88ddd1f5ade8f3f48728a
 F src/walker.c 3112bb3afe1d85dc52317cb1d752055e9a781f8f
-F src/where.c 24d95b218176bad38ae2abe73197c28d3d6ef9a6
+F src/where.c 118896232fe70b1ac9c2ef2811675d5bef8b9c40
 F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
@@ -260,13 +260,13 @@ F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
 F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
 F test/alter4.test b2debc14d8cbe4c1d12ccd6a41eef88a8c1f15d5
 F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
-F test/analyze.test 68b43c1f9cd6ffc3bbb30d27a23712b38c413eca
+F test/analyze.test f8ab7d15858b4093b06caf5e57e2a5ff7104bdae
 F test/analyze2.test 8f2b1534d43f5547ce9a6b736c021d4192c75be3
-F test/analyze3.test d61f55d8b472fc6e713160b1e577f7a68e63f38b
+F test/analyze3.test d5e4da00a37b927d83aead50626c254a785c111f
 F test/analyze4.test 757b37875cf9bb528d46f74497bc789c88365045
-F test/analyze5.test 1de8d66b11aae5a1453aa042d62e834a476bac9c
+F test/analyze5.test 713354664c5ff1853ab2cbcb740f0cf5cb7c802e
 F test/analyze6.test c125622a813325bba1b4999040ddc213773c2290
-F test/analyze7.test 5508e7828164ea0b518ed219bed7320a481863d4
+F test/analyze7.test d3587aa5af75c9048d031b94fceca2534fa75d1d
 F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
 F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
 F test/async3.test d73a062002376d7edc1fe3edff493edbec1fc2f7
@@ -359,7 +359,7 @@ F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
 F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
 F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
 F test/date.test a18a2ce81add84b17b06559e82ad7bb91bc6ddff
-F test/dbstatus.test a719af0f226bd280748a4bb9054c0a5a9fc1b16c
+F test/dbstatus.test 9eb484ba837c6f3f9bbcaecc29e6060a8c3ba6d2
 F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
 F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
 F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
@@ -682,7 +682,7 @@ F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
 F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
 F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
 F test/stat.test 0997f6a57a35866b14111ed361ed8851ce7978ae
-F test/stat3.test 44cec64164a2f5d86960343a118bc0bdac754f61
+F test/stat3.test 986d735f70ef62a1daf98e8762f35fa3b062c5c3
 F test/stmt.test 25d64e3dbf9a3ce89558667d7f39d966fe2a71b9
 F test/subquery.test b524f57c9574b2c0347045b4510ef795d4686796
 F test/subselect.test d24fd8757daf97dafd2e889c73ea4c4272dcf4e4
@@ -851,7 +851,7 @@ F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
 F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
 F test/unique.test 083c7fff74695bcc27a71d75699deba3595bc9c2
 F test/unixexcl.test 9d80a54d86d2261f660758928959368ffc36151e
-F test/unordered.test e81169ce2a8f31b2c6b66af691887e1376ab3ced
+F test/unordered.test f53095cee37851bf30130fa1bf299a8845e837bb
 F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172
 F test/uri.test 53de9a2549cbda9c343223236918ef502f6a9051
 F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
@@ -958,7 +958,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262
-P 8225924ea015a0c331b69134139922ec83f989f8
-R 26e2ba931d588fb68b0f6f40c6d0c97e
+P 1dcd24283e6c1cc638eb9ffac434046447f88769
+R d1b65b54090c71db8593e348e48cfb27
 U drh
-Z 3074616e4d36d00fd7fabd4dfdb13fe0
+Z 11276de2d321825346f710e3928eda70
index 167b946d451ec11530bfe7b90b2283df287f60a0..12a95a47e2fe1688055a3beb1b77e31362e6e1ce 100644 (file)
@@ -1 +1 @@
-1dcd24283e6c1cc638eb9ffac434046447f88769
\ No newline at end of file
+89b2f70884cad0abdf4c66cb64ecddb2820ded74
\ No newline at end of file
index 05512ce3c9a291485f6b2dae12ddef543db5f7d9..f67e26e8c1b04b088825a55eb8cdbb20f7606318 100644 (file)
@@ -957,6 +957,7 @@ static int loadStat3(sqlite3 *db, const char *zDb){
     assert( pIdx->nSample==0 );
     pIdx->nSample = (u8)nSample;
     pIdx->aSample = sqlite3MallocZero( nSample*sizeof(IndexSample) );
+    pIdx->avgEq = pIdx->aiRowEst[1];
     if( pIdx->aSample==0 ){
       db->mallocFailed = 1;
       sqlite3_finalize(pStmt);
@@ -966,7 +967,7 @@ static int loadStat3(sqlite3 *db, const char *zDb){
   sqlite3_finalize(pStmt);
 
   zSql = sqlite3MPrintf(db, 
-      "SELECT idx,nlt,neq,sample FROM %Q.sqlite_stat3", zDb);
+      "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb);
   if( !zSql ){
     return SQLITE_NOMEM;
   }
@@ -977,6 +978,8 @@ static int loadStat3(sqlite3 *db, const char *zDb){
   while( sqlite3_step(pStmt)==SQLITE_ROW ){
     char *zIndex;   /* Index name */
     Index *pIdx;    /* Pointer to the index object */
+    int i;          /* Loop counter */
+    tRowcnt sumEq;  /* Sum of the nEq values */
 
     zIndex = (char *)sqlite3_column_text(pStmt, 0);
     if( zIndex==0 ) continue;
@@ -990,17 +993,25 @@ static int loadStat3(sqlite3 *db, const char *zDb){
     }
     assert( idx<pIdx->nSample );
     pSample = &pIdx->aSample[idx];
-    pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 1);
-    pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 2);
-    eType = sqlite3_column_type(pStmt, 3);
+    pSample->nEq = (tRowcnt)sqlite3_column_int64(pStmt, 1);
+    pSample->nLt = (tRowcnt)sqlite3_column_int64(pStmt, 2);
+    pSample->nDLt = (tRowcnt)sqlite3_column_int64(pStmt, 3);
+    if( idx==pIdx->nSample-1 ){
+      if( pSample->nDLt>0 ){
+        for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq;
+        pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt;
+      }
+      if( pIdx->avgEq<=0 ) pIdx->avgEq = 1;
+    }
+    eType = sqlite3_column_type(pStmt, 4);
     pSample->eType = (u8)eType;
     switch( eType ){
       case SQLITE_INTEGER: {
-        pSample->u.i = sqlite3_column_int64(pStmt, 3);
+        pSample->u.i = sqlite3_column_int64(pStmt, 4);
         break;
       }
       case SQLITE_FLOAT: {
-        pSample->u.r = sqlite3_column_double(pStmt, 3);
+        pSample->u.r = sqlite3_column_double(pStmt, 4);
         break;
       }
       case SQLITE_NULL: {
@@ -1009,10 +1020,10 @@ static int loadStat3(sqlite3 *db, const char *zDb){
       default: assert( eType==SQLITE_TEXT || eType==SQLITE_BLOB ); {
         const char *z = (const char *)(
               (eType==SQLITE_BLOB) ?
-              sqlite3_column_blob(pStmt, 3):
-              sqlite3_column_text(pStmt, 3)
+              sqlite3_column_blob(pStmt, 4):
+              sqlite3_column_text(pStmt, 4)
            );
-        int n = sqlite3_column_bytes(pStmt, 2);
+        int n = sqlite3_column_bytes(pStmt, 4);
         if( n>0xffff ) n = 0xffff;
         pSample->nByte = (u16)n;
         if( n < 1){
index 73c51c8550dd5a3bf9a5066f8869ae4e2fefa7a8..7277a42d0c4abc0d390b71619fb7478ec06b30d4 100644 (file)
@@ -2062,7 +2062,6 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
   sqlite3NestedParse(pParse, 
       "DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
       pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
-  sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
   if( !isView && !IsVirtual(pTab) ){
     destroyTable(pParse, pTab);
   }
@@ -2174,6 +2173,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
     sqlite3BeginWriteOperation(pParse, 1, iDb);
     sqlite3FkDropTable(pParse, pName, pTab);
     sqlite3CodeDropTable(pParse, pTab, iDb, isView);
+    sqlite3ClearStatTables(pParse, iDb, "tbl", pTab->zName);
   }
 
 exit_drop_table:
index 6bb14b60b816291bed52b20a2c13247022184809..f437b20370e02c0645fb3cb068fd71e186e82050 100644 (file)
@@ -1502,6 +1502,7 @@ struct Index {
   u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
   char **azColl;   /* Array of collation sequence names for index */
 #ifdef SQLITE_ENABLE_STAT3
+  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
   IndexSample *aSample;    /* Samples of the left-most key */
 #endif
 };
@@ -1520,6 +1521,7 @@ struct IndexSample {
   u16 nByte;        /* Size in byte of text or blob. */
   tRowcnt nEq;      /* Est. number of rows where the key equals this sample */
   tRowcnt nLt;      /* Est. number of rows where key is less than this sample */
+  tRowcnt nDLt;     /* Est. number of distinct keys less than this sample */
 };
 
 /*
index 3118a0a0e1ff11c96fb69b6de90ace8a82258dbf..fe8bd90498f2c9e6820ca6b737a3718479721473 100644 (file)
@@ -2441,6 +2441,8 @@ static int whereKeyStats(
   IndexSample *aSample;
   int i, eType;
   int isEq = 0;
+  i64 v;
+  double r, rS;
 
   assert( roundUp==0 || roundUp==1 );
   if( pVal==0 ) return SQLITE_ERROR;
@@ -2450,22 +2452,36 @@ static int whereKeyStats(
   eType = sqlite3_value_type(pVal);
 
   if( eType==SQLITE_INTEGER ){
-    i64 v = sqlite3_value_int64(pVal);
+    v = sqlite3_value_int64(pVal);
+    r = (i64)v;
     for(i=0; i<pIdx->nSample; i++){
       if( aSample[i].eType==SQLITE_NULL ) continue;
       if( aSample[i].eType>=SQLITE_TEXT ) break;
-      if( aSample[i].u.i>=v ){
-        isEq = aSample[i].u.i==v;
-        break;
+      if( aSample[i].eType==SQLITE_INTEGER ){
+        if( aSample[i].u.i>=v ){
+          isEq = aSample[i].u.i==v;
+          break;
+        }
+      }else{
+        assert( aSample[i].eType==SQLITE_FLOAT );
+        if( aSample[i].u.r>=r ){
+          isEq = aSample[i].u.r==r;
+          break;
+        }
       }
     }
   }else if( eType==SQLITE_FLOAT ){
-    double r = sqlite3_value_double(pVal);
+    r = sqlite3_value_double(pVal);
     for(i=0; i<pIdx->nSample; i++){
       if( aSample[i].eType==SQLITE_NULL ) continue;
       if( aSample[i].eType>=SQLITE_TEXT ) break;
-      if( aSample[i].u.r>=r ){
-        isEq = aSample[i].u.r==r;
+      if( aSample[i].eType==SQLITE_FLOAT ){
+        rS = aSample[i].u.r;
+      }else{
+        rS = aSample[i].u.i;
+      }
+      if( rS>=r ){
+        isEq = rS==r;
         break;
       }
     }
@@ -2546,14 +2562,11 @@ static int whereKeyStats(
     if( i==0 ){
       iLower = 0;
       iUpper = aSample[0].nLt;
-    }else if( i>=pIdx->nSample ){
-      iUpper = n;
-      iLower = aSample[i].nEq + aSample[i].nLt;
     }else{
+      iUpper = i>=pIdx->nSample ? n : aSample[i].nLt;
       iLower = aSample[i-1].nEq + aSample[i-1].nLt;
-      iUpper = aSample[i].nLt;
     }
-    aStat[1] = pIdx->aiRowEst[1];
+    aStat[1] = pIdx->avgEq;
     if( iLower>=iUpper ){
       iGap = 0;
     }else{
@@ -2651,7 +2664,7 @@ static int whereRangeScanEst(
   int nEq,             /* index into p->aCol[] of the range-compared column */
   WhereTerm *pLower,   /* Lower bound on the range. ex: "x>123" Might be NULL */
   WhereTerm *pUpper,   /* Upper bound on the range. ex: "x<455" Might be NULL */
-  tRowcnt *pRangeDiv   /* OUT: Reduce search space by this divisor */
+  double *pRangeDiv   /* OUT: Reduce search space by this divisor */
 ){
   int rc = SQLITE_OK;
 
@@ -2684,18 +2697,18 @@ static int whereRangeScanEst(
        && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
       ){
         iUpper = a[0];
-        if( pLower->eOperator==WO_LE ) iUpper += a[1];
+        if( pUpper->eOperator==WO_LE ) iUpper += a[1];
       }
       sqlite3ValueFree(pRangeVal);
     }
     if( rc==SQLITE_OK ){
       if( iUpper<=iLower ){
-        *pRangeDiv = p->aiRowEst[0];
+        *pRangeDiv = (double)p->aiRowEst[0];
       }else{
-        *pRangeDiv = p->aiRowEst[0]/(iUpper - iLower);
+        *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower);
       }
-      WHERETRACE(("range scan regions: %u..%u  div=%u\n",
-                  (u32)iLower, (u32)iUpper, (u32)*pRangeDiv));
+      WHERETRACE(("range scan regions: %u..%u  div=%g\n",
+                  (u32)iLower, (u32)iUpper, *pRangeDiv));
       return SQLITE_OK;
     }
   }
@@ -2705,9 +2718,9 @@ static int whereRangeScanEst(
   UNUSED_PARAMETER(nEq);
 #endif
   assert( pLower || pUpper );
-  *pRangeDiv = 1;
-  if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= 4;
-  if( pUpper ) *pRangeDiv *= 4;
+  *pRangeDiv = (double)1;
+  if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ) *pRangeDiv *= (double)4;
+  if( pUpper ) *pRangeDiv *= (double)4;
   return rc;
 }
 
@@ -2976,7 +2989,7 @@ static void bestBtreeIndex(
     int nEq;                      /* Number of == or IN terms matching index */
     int bInEst = 0;               /* True if "x IN (SELECT...)" seen */
     int nInMul = 1;               /* Number of distinct equalities to lookup */
-    tRowcnt rangeDiv = 1;         /* Estimated reduction in search space */
+    double rangeDiv = (double)1;  /* Estimated reduction in search space */
     int nBound = 0;               /* Number of range constraints seen */
     int bSort = !!pOrderBy;       /* True if external sort required */
     int bDist = !!pDistinct;      /* True if index cannot help with DISTINCT */
@@ -3111,7 +3124,7 @@ static void bestBtreeIndex(
     /* Adjust the number of output rows and downward to reflect rows
     ** that are excluded by range constraints.
     */
-    nRow = nRow/(double)rangeDiv;
+    nRow = nRow/rangeDiv;
     if( nRow<1 ) nRow = 1;
 
     /* Experiments run on real SQLite databases show that the time needed
index 6bb8cc363ce487b79607f7b51d8a3e9fce171956..362702a9c2cfd7a2e65ce67af5fff8dc1c317434 100644 (file)
@@ -288,7 +288,7 @@ do_test analyze-4.3 {
 } {}
 
 # Verify that DROP TABLE and DROP INDEX remove entries from the 
-# sqlite_stat1 and sqlite_stat2 tables.
+# sqlite_stat1 and sqlite_stat3 tables.
 #
 do_test analyze-5.0 {
   execsql {
@@ -306,11 +306,11 @@ do_test analyze-5.0 {
     SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
   }
 } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
-ifcapable stat2 {
+ifcapable stat3 {
   do_test analyze-5.1 {
     execsql {
-      SELECT DISTINCT idx FROM sqlite_stat2 ORDER BY 1;
-      SELECT DISTINCT tbl FROM sqlite_stat2 ORDER BY 1;
+      SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
+      SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
     }
   } {t3i1 t3i2 t3i3 t4i1 t4i2 t3 t4}
 }
@@ -321,11 +321,11 @@ do_test analyze-5.2 {
     SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
   }
 } {t3i1 t3i3 t4i1 t4i2 t3 t4}
-ifcapable stat2 {
+ifcapable stat3 {
   do_test analyze-5.3 {
     execsql {
-      SELECT DISTINCT idx FROM sqlite_stat2 ORDER BY 1;
-      SELECT DISTINCT tbl FROM sqlite_stat2 ORDER BY 1;
+      SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
+      SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
     }
   } {t3i1 t3i3 t4i1 t4i2 t3 t4}
 }
@@ -336,11 +336,11 @@ do_test analyze-5.4 {
     SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1;
   }
 } {t4i1 t4i2 t4}
-ifcapable stat2 {
+ifcapable stat3 {
   do_test analyze-5.5 {
     execsql {
-      SELECT DISTINCT idx FROM sqlite_stat2 ORDER BY 1;
-      SELECT DISTINCT tbl FROM sqlite_stat2 ORDER BY 1;
+      SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1;
+      SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1;
     }
   } {t4i1 t4i2 t4}
 }
index 2378ffaaba9a129212d932d94dfa08fb8050856f..2c8e42d607197755c5acd3a5e09d827643923872 100644 (file)
@@ -97,10 +97,10 @@ do_test analyze3-1.1.1 {
 
 do_eqp_test analyze3-1.1.2 {
   SELECT sum(y) FROM t1 WHERE x>200 AND x<300
-} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?) (~100 rows)}}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?) (~179 rows)}}
 do_eqp_test analyze3-1.1.3 {
   SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 
-} {0 0 0 {SCAN TABLE t1 (~111 rows)}}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? and x<?) {~959 rows)}}
 
 do_test analyze3-1.1.4 {
   sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
@@ -193,7 +193,7 @@ do_test analyze3-1.3.1 {
 } {}
 do_eqp_test analyze3-1.3.2 {
   SELECT sum(y) FROM t3 WHERE x>200 AND x<300
-} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?) (~100 rows)}}
+} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?) (~166 rows)}}
 do_eqp_test analyze3-1.3.3 {
   SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
 } {0 0 0 {SCAN TABLE t3 (~111 rows)}}
@@ -248,7 +248,7 @@ do_test analyze3-2.1 {
 } {}
 do_eqp_test analyze3-2.2 {
   SELECT count(a) FROM t1 WHERE b LIKE 'a%'
-} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?) (~30000 rows)}}
+} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?) (~31250 rows)}}
 do_eqp_test analyze3-2.3 {
   SELECT count(a) FROM t1 WHERE b LIKE '%a'
 } {0 0 0 {SCAN TABLE t1 (~500000 rows)}}
index a0469da12546cb35308b47bea72a43bfcb35f6e9..1041d709d2c3619b9f457213eeb75fe63e2e701d 100644 (file)
 #***********************************************************************
 #
 # This file implements tests for SQLite library.  The focus of the tests
-# in this file is the use of the sqlite_stat2 histogram data on tables
+# in this file is the use of the sqlite_stat3 histogram data on tables
 # with many repeated values and only a few distinct values.
 #
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 
-ifcapable !stat2 {
+ifcapable !stat3 {
   finish_test
   return
 }
@@ -55,114 +55,102 @@ do_test analyze5-1.0 {
     CREATE INDEX t1y ON t1(y);  -- integers 0 and very few 1s
     CREATE INDEX t1z ON t1(z);  -- integers 0, 1, 2, and 3
     ANALYZE;
-    SELECT sample FROM sqlite_stat2 WHERE idx='t1u' ORDER BY sampleno;
+    SELECT sample FROM sqlite_stat3 WHERE idx='t1u' ORDER BY nlt;
   }
-} {alpha alpha alpha alpha bravo bravo bravo charlie charlie delta}
+} {alpha bravo charlie delta}
+
 do_test analyze5-1.1 {
-  string tolower \
-   [db eval {SELECT sample from sqlite_stat2 WHERE idx='t1v' ORDER BY sampleno}]
-} {alpha alpha alpha alpha bravo bravo bravo charlie charlie delta}
+  db eval {SELECT DISTINCT lower(sample) FROM sqlite_stat3 WHERE idx='t1v'
+             ORDER BY 1}
+} {alpha bravo charlie delta}
 do_test analyze5-1.2 {
-  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1w' ORDER BY sampleno}
-} {{} 0 0 0 0 1 1 1 2 2}
-do_test analyze5-1.3 {
-  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1x' ORDER BY sampleno}
-} {{} {} {} {} 1 1 1 2 2 3}
-do_test analyze5-1.4 {
-  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1y' ORDER BY sampleno}
-} {0 0 0 0 0 0 0 0 0 0}
-do_test analyze5-1.5 {
-  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1z' ORDER BY sampleno}
-} {0 0 0 0 1 1 1 2 2 3}
-do_test analyze5-1.6 {
-  db eval {SELECT sample from sqlite_stat2 WHERE idx='t1t' ORDER BY sampleno}
-} {0.5 0.5 0.5 0.5 1.5 1.5 1.5 2.5 2.5 3.5}
-
+  db eval {SELECT idx, count(*) FROM sqlite_stat3 GROUP BY 1 ORDER BY 1}
+} {t1t 4 t1u 4 t1v 4 t1w 4 t1x 4 t1y 2 t1z 4}
 
 # Verify that range queries generate the correct row count estimates
 #
 foreach {testid where index rows} {
     1  {z>=0 AND z<=0}       t1z  400
     2  {z>=1 AND z<=1}       t1z  300
-    3  {z>=2 AND z<=2}       t1z  200
-    4  {z>=3 AND z<=3}       t1z  100
-    5  {z>=4 AND z<=4}       t1z   50
-    6  {z>=-1 AND z<=-1}     t1z   50
-    7  {z>1 AND z<3}         t1z  200
+    3  {z>=2 AND z<=2}       t1z  175
+    4  {z>=3 AND z<=3}       t1z  125
+    5  {z>=4 AND z<=4}       t1z    1
+    6  {z>=-1 AND z<=-1}     t1z    1
+    7  {z>1 AND z<3}         t1z  175
     8  {z>0 AND z<100}       t1z  600
     9  {z>=1 AND z<100}      t1z  600
    10  {z>1 AND z<100}       t1z  300
    11  {z>=2 AND z<100}      t1z  300
-   12  {z>2 AND z<100}       t1z  100
-   13  {z>=3 AND z<100}      t1z  100
-   14  {z>3 AND z<100}       t1z   50
-   15  {z>=4 AND z<100}      t1z   50
-   16  {z>=-100 AND z<=-1}   t1z   50
+   12  {z>2 AND z<100}       t1z  125
+   13  {z>=3 AND z<100}      t1z  125
+   14  {z>3 AND z<100}       t1z    1
+   15  {z>=4 AND z<100}      t1z    1
+   16  {z>=-100 AND z<=-1}   t1z    1
    17  {z>=-100 AND z<=0}    t1z  400
-   18  {z>=-100 AND z<0}     t1z   50
+   18  {z>=-100 AND z<0}     t1z    1
    19  {z>=-100 AND z<=1}    t1z  700
    20  {z>=-100 AND z<2}     t1z  700
-   21  {z>=-100 AND z<=2}    t1z  900
-   22  {z>=-100 AND z<3}     t1z  900
+   21  {z>=-100 AND z<=2}    t1z  875
+   22  {z>=-100 AND z<3}     t1z  875
   
    31  {z>=0.0 AND z<=0.0}   t1z  400
    32  {z>=1.0 AND z<=1.0}   t1z  300
-   33  {z>=2.0 AND z<=2.0}   t1z  200
-   34  {z>=3.0 AND z<=3.0}   t1z  100
-   35  {z>=4.0 AND z<=4.0}   t1z   50
-   36  {z>=-1.0 AND z<=-1.0} t1z   50
-   37  {z>1.5 AND z<3.0}     t1z  200
-   38  {z>0.5 AND z<100}     t1z  600
+   33  {z>=2.0 AND z<=2.0}   t1z  175
+   34  {z>=3.0 AND z<=3.0}   t1z  125
+   35  {z>=4.0 AND z<=4.0}   t1z    1
+   36  {z>=-1.0 AND z<=-1.0} t1z    1
+   37  {z>1.5 AND z<3.0}     t1z  174
+   38  {z>0.5 AND z<100}     t1z  599
    39  {z>=1.0 AND z<100}    t1z  600
-   40  {z>1.5 AND z<100}     t1z  300
+   40  {z>1.5 AND z<100}     t1z  299
    41  {z>=2.0 AND z<100}    t1z  300
-   42  {z>2.1 AND z<100}     t1z  100
-   43  {z>=3.0 AND z<100}    t1z  100
-   44  {z>3.2 AND z<100}     t1z   50
-   45  {z>=4.0 AND z<100}    t1z   50
-   46  {z>=-100 AND z<=-1.0} t1z   50
+   42  {z>2.1 AND z<100}     t1z  124
+   43  {z>=3.0 AND z<100}    t1z  125
+   44  {z>3.2 AND z<100}     t1z    1
+   45  {z>=4.0 AND z<100}    t1z    1
+   46  {z>=-100 AND z<=-1.0} t1z    1
    47  {z>=-100 AND z<=0.0}  t1z  400
-   48  {z>=-100 AND z<0.0}   t1z   50
+   48  {z>=-100 AND z<0.0}   t1z    1
    49  {z>=-100 AND z<=1.0}  t1z  700
    50  {z>=-100 AND z<2.0}   t1z  700
-   51  {z>=-100 AND z<=2.0}  t1z  900
-   52  {z>=-100 AND z<3.0}   t1z  900
+   51  {z>=-100 AND z<=2.0}  t1z  875
+   52  {z>=-100 AND z<3.0}   t1z  875
   
-  101  {z=-1}                t1z   50
+  101  {z=-1}                t1z    1
   102  {z=0}                 t1z  400
   103  {z=1}                 t1z  300
-  104  {z=2}                 t1z  200
-  105  {z=3}                 t1z  100
-  106  {z=4}                 t1z   50
-  107  {z=-10.0}             t1z   50
+  104  {z=2}                 t1z  175
+  105  {z=3}                 t1z  125
+  106  {z=4}                 t1z    1
+  107  {z=-10.0}             t1z    1
   108  {z=0.0}               t1z  400
   109  {z=1.0}               t1z  300
-  110  {z=2.0}               t1z  200
-  111  {z=3.0}               t1z  100
-  112  {z=4.0}               t1z   50
-  113  {z=1.5}               t1z   50
-  114  {z=2.5}               t1z   50
+  110  {z=2.0}               t1z  175
+  111  {z=3.0}               t1z  125
+  112  {z=4.0}               t1z    1
+  113  {z=1.5}               t1z    1
+  114  {z=2.5}               t1z    1
   
-  201  {z IN (-1)}           t1z   50
+  201  {z IN (-1)}           t1z    1
   202  {z IN (0)}            t1z  400
   203  {z IN (1)}            t1z  300
-  204  {z IN (2)}            t1z  200
-  205  {z IN (3)}            t1z  100
-  206  {z IN (4)}            t1z   50
-  207  {z IN (0.5)}          t1z   50
+  204  {z IN (2)}            t1z  175
+  205  {z IN (3)}            t1z  125
+  206  {z IN (4)}            t1z    1
+  207  {z IN (0.5)}          t1z    1
   208  {z IN (0,1)}          t1z  700
-  209  {z IN (0,1,2)}        t1z  900
+  209  {z IN (0,1,2)}        t1z  875
   210  {z IN (0,1,2,3)}      {}   100
   211  {z IN (0,1,2,3,4,5)}  {}   100
-  212  {z IN (1,2)}          t1z  500
+  212  {z IN (1,2)}          t1z  475
   213  {z IN (2,3)}          t1z  300
   214  {z=3 OR z=2}          t1z  300
-  215  {z IN (-1,3)}         t1z  150
-  216  {z=-1 OR z=3}         t1z  150
+  215  {z IN (-1,3)}         t1z  126
+  216  {z=-1 OR z=3}         t1z  126
 
-  300  {y=0}                 {}   100
-  301  {y=1}                 t1y   50
-  302  {y=0.1}               t1y   50
+  300  {y=0}                 t1y  974
+  301  {y=1}                 t1y   26
+  302  {y=0.1}               t1y    1
 
   400  {x IS NULL}           t1x  400
 
@@ -204,16 +192,17 @@ db eval {
 # Verify that range queries generate the correct row count estimates
 #
 foreach {testid where index rows} {
-  500  {x IS NULL AND u='charlie'}         t1u  20
-  501  {x=1 AND u='charlie'}               t1x   5
-  502  {x IS NULL}                          {} 100
-  503  {x=1}                               t1x  50
-  504  {x IS NOT NULL}                     t1x  25
+  500  {x IS NULL AND u='charlie'}         t1u  17
+  501  {x=1 AND u='charlie'}               t1x   1
+  502  {x IS NULL}                         t1x 995
+  503  {x=1}                               t1x   1
+  504  {x IS NOT NULL}                     t1x   2
   505  {+x IS NOT NULL}                     {} 500
   506  {upper(x) IS NOT NULL}               {} 500
 
 } {
   # Verify that the expected index is used with the expected row count
+if {$testid==50299} {breakpoint; set sqlite_where_trace 1}
   do_test analyze5-1.${testid}a {
     set x [lindex [eqp "SELECT * FROM t1 WHERE $where"] 3]
     set idx {}
@@ -221,6 +210,7 @@ foreach {testid where index rows} {
     regexp {~([0-9]+) rows} $x all nrow
     list $idx $nrow
   } [list $index $rows]
+if {$testid==50299} exit
 
   # Verify that the same result is achieved regardless of whether or not
   # the index is used
index 4892a2233a16537e71a5f62e76bf1269b072d548..5bdb04d72cad4102a514027f0e9f83b1c46c02ed 100644 (file)
@@ -82,14 +82,14 @@ do_test analyze7-3.1 {
 do_test analyze7-3.2.1 {
   execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
 } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~86 rows)}}
-ifcapable stat2 {
-  # If ENABLE_STAT2 is defined, SQLite comes up with a different estimated
+ifcapable stat3 {
+  # If ENABLE_STAT3 is defined, SQLite comes up with a different estimated
   # row count for (c=2) than it does for (c=?).
   do_test analyze7-3.2.2 {
     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
-  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~51 rows)}}
+  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?) (~57 rows)}}
 } else {
-  # If ENABLE_STAT2 is not defined, the expected row count for (c=2) is the
+  # If ENABLE_STAT3 is not defined, the expected row count for (c=2) is the
   # same as that for (c=?).
   do_test analyze7-3.2.3 {
     execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
@@ -98,12 +98,14 @@ ifcapable stat2 {
 do_test analyze7-3.3 {
   execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
 } {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
-do_test analyze7-3.4 {
-  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
-} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~2 rows)}}
-do_test analyze7-3.5 {
-  execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
-} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+ifcapable {!stat3} {
+  do_test analyze7-3.4 {
+    execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
+  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?) (~2 rows)}}
+  do_test analyze7-3.5 {
+    execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
+  } {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?) (~1 rows)}}
+}
 do_test analyze7-3.6 {
   execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
 } {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?) (~1 rows)}}
index 39522f4857cd89639794bd6e27804d08446535d4..e1c8f3ebbf9edf0199bcb17bd1e2e099aeb1f8ba 100644 (file)
@@ -56,6 +56,12 @@ proc lookaside {db} {
   }
 }
 
+ifcapable stat3 {
+  set STAT3 1
+} else {
+  set STAT3 0
+}
+
 #---------------------------------------------------------------------------
 # Run the dbstatus-2 and dbstatus-3 tests with several of different
 # lookaside buffer sizes.
@@ -118,7 +124,7 @@ foreach ::lookaside_buffer_size {0 64 120} {
       CREATE TABLE t2(c, d);
       CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
     }
-    6 {
+    6y {
       CREATE TABLE t1(a, b);
       CREATE INDEX i1 ON t1(a);
       CREATE INDEX i2 ON t1(a,b);
@@ -198,7 +204,11 @@ foreach ::lookaside_buffer_size {0 64 120} {
     # much greater than just that reported by DBSTATUS_SCHEMA_USED in this
     # case.
     #
-    if {[string match *x $tn] || $AUTOVACUUM} {
+    # Some of the memory used for sqlite_stat3 is unaccounted for by
+    # dbstatus.
+    #
+    if {[string match *x $tn] || $AUTOVACUUM
+         || ([string match *y $tn] && $STAT3)} {
       do_test dbstatus-2.$tn.ax { expr {($nSchema1-$nSchema2)<=$nFree} } 1
     } else {
       do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
index 780a69ce670c0abf1fa485696bffaab49f66161c..6c848192c12516ba1e900ccaff7e738d072017f9 100644 (file)
@@ -11,7 +11,7 @@
 #
 # This file implements regression tests for SQLite library. This file 
 # implements tests for the extra functionality provided by the ANALYZE 
-# command when the library is compiled with SQLITE_ENABLE_STAT2 defined.
+# command when the library is compiled with SQLITE_ENABLE_STAT3 defined.
 #
 
 set testdir [file dirname $argv0]
@@ -28,7 +28,7 @@ do_test 1.1 {
   db eval {
     PRAGMA writable_schema=ON;
     CREATE TABLE sqlite_stat2(tbl,idx,sampleno,sample);
-    CREATE TABLE sqlite_stat3(tbl,idx,sampleno,sample,neq,nlt);
+    CREATE TABLE sqlite_stat3(tbl,idx,neq,nlt,ndlt,sample);
     SELECT name FROM sqlite_master ORDER BY 1;
   }
 } {sqlite_stat2 sqlite_stat3}
index a9c62534329a84e7082773f2f5bba3e1b2353e43..6c7c2bb25b0c755fd82e0c47f869bee4291118cc 100644 (file)
@@ -31,11 +31,13 @@ do_execsql_test 1.0 {
 } {}
 
 foreach idxmode {ordered unordered} {
+  catchsql { DELETE FROM sqlite_stat2 }
+  catchsql { DELETE FROM sqlite_stat3 }
   if {$idxmode == "unordered"} {
     execsql { UPDATE sqlite_stat1 SET stat = stat || ' unordered' }
-    db close
-    sqlite3 db test.db
   }
+  db close
+  sqlite3 db test.db
   foreach {tn sql r(ordered) r(unordered)} {
     1   "SELECT * FROM t1 ORDER BY a"
         {0 0 0 {SCAN TABLE t1 USING INDEX i1 (~128 rows)}}