From: drh Date: Mon, 29 Feb 2016 18:30:30 +0000 (+0000) Subject: Modify the ANALYZE command to store worst-case statistics in sqlite_stat1, X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0cf8896ec8c607bdad237c1510ecb12f4ca405f8;p=thirdparty%2Fsqlite.git Modify the ANALYZE command to store worst-case statistics in sqlite_stat1, rather thn average case. FossilOrigin-Name: 5a0143c94ec0682798f3c09fba63593e695d2e2d --- diff --git a/manifest b/manifest index bacddf080c..530227dd48 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\sin\sfts5\swhere\sa\scorrupt\sdb\scould\slead\sto\sa\s(huge)\sbuffer\soverread. -D 2016-02-29T17:34:16.069 +C Modify\sthe\sANALYZE\scommand\sto\sstore\sworst-case\sstatistics\sin\ssqlite_stat1,\nrather\sthn\saverage\scase. +D 2016-02-29T18:30:30.116 F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079 @@ -286,7 +286,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 44e18dfd78e8942d65d3cdaec4de972b5cd9f1f2 -F src/analyze.c ab57b6763dd4c6170a20673d14882c033affd188 +F src/analyze.c 37343619c6c560722aac521d156d34ebff746526 F src/attach.c a3724c64de1099d85e30751213d285752aed9505 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce @@ -1451,7 +1451,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 251d6473f7c9ad95adbdcc49cb8eaf7c0956764b -R 1a43d3061a1f154a38fc05ffa17e1f4a -U dan -Z 0ef60cd2035dd9bea82e9df13f5bcf57 +P c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f +R 180de557065fd2bddac753825b6be69a +T *branch * analyze-worst-case +T *sym-analyze-worst-case * +T -sym-trunk * +U drh +Z 3d046dcd3035333c5259dea36a77e4b0 diff --git a/manifest.uuid b/manifest.uuid index 2a4a25da5e..49afe15d1c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f \ No newline at end of file +5a0143c94ec0682798f3c09fba63593e695d2e2d \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index cd59ae681d..f4c058e232 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -267,6 +267,7 @@ typedef struct Stat4Sample Stat4Sample; struct Stat4Sample { tRowcnt *anEq; /* sqlite_stat4.nEq */ tRowcnt *anDLt; /* sqlite_stat4.nDLt */ + tRowcnt *amxEq; /* Maximum length run of equal values */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 tRowcnt *anLt; /* sqlite_stat4.nLt */ union { @@ -418,8 +419,9 @@ static void statInit( /* Allocate the space required for the Stat4Accum object */ n = sizeof(*p) + sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */ - + sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */ + + sizeof(tRowcnt)*nColUp /* Stat4Accum.amxEq */ #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + + sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */ + sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */ + sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */ + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample) @@ -436,18 +438,19 @@ static void statInit( p->nRow = 0; p->nCol = nCol; p->nKeyCol = nKeyCol; - p->current.anDLt = (tRowcnt*)&p[1]; - p->current.anEq = &p->current.anDLt[nColUp]; + p->current.anEq = (tRowcnt*)&p[1]; + p->current.amxEq = &p->current.anEq[nColUp]; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 { u8 *pSpace; /* Allocated space not yet assigned */ - int i; /* Used to iterate through p->aSample[] */ + int i; /* Loop counter */ p->iGet = -1; p->mxSample = mxSample; p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1); - p->current.anLt = &p->current.anEq[nColUp]; + p->current.anDLt = &p->current.amxEq[nColUp]; + p->current.anLt = &p->current.anDLt[nColUp]; p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); /* Set up the Stat4Accum.a[] and aBest[] arrays */ @@ -721,7 +724,10 @@ static void statPush( if( p->nRow==0 ){ /* This is the first call to this function. Do initialization. */ - for(i=0; inCol; i++) p->current.anEq[i] = 1; + for(i=0; inCol; i++){ + p->current.anEq[i] = 1; + p->current.amxEq[i] = 1; + } }else{ /* Second and subsequent calls get processed here */ samplePushPrevious(p, iChng); @@ -729,11 +735,12 @@ static void statPush( /* Update anDLt[], anLt[] and anEq[] to reflect the values that apply ** to the current row of the index. */ for(i=0; icurrent.amxEq[i]==p->current.anEq[i] ) p->current.amxEq[i]++; p->current.anEq[i]++; } for(i=iChng; inCol; i++){ - p->current.anDLt[i]++; #ifdef SQLITE_ENABLE_STAT3_OR_STAT4 + p->current.anDLt[i]++; p->current.anLt[i] += p->current.anEq[i]; #endif p->current.anEq[i] = 1; @@ -828,7 +835,7 @@ static void statGet( ** the index. The first integer in the list is the total number of ** entries in the index. There is one additional integer in the list ** for each indexed column. This additional integer is an estimate of - ** the number of rows matched by a stabbing query on the index using + ** the number of rows matched by a query on the index using ** a key with the corresponding number of fields. In other words, ** if the index is on columns (a,b) and the sqlite_stat1 value is ** "100 10 2", then SQLite estimates that: @@ -837,10 +844,8 @@ static void statGet( ** * "WHERE a=?" matches 10 rows, and ** * "WHERE a=? AND b=?" matches 2 rows. ** - ** If D is the count of distinct values and K is the total number of - ** rows, then each estimate is computed as: - ** - ** I = (K+D-1)/D + ** Use the worst-case estimate: the maximum number of repeated entries + ** in the index. */ char *z; int i; @@ -854,8 +859,7 @@ static void statGet( sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow); z = zRet + sqlite3Strlen30(zRet); for(i=0; inKeyCol; i++){ - u64 nDistinct = p->current.anDLt[i] + 1; - u64 iVal = (p->nRow + nDistinct - 1) / nDistinct; + u64 iVal = p->current.amxEq[i]; sqlite3_snprintf(24, z, " %llu", iVal); z += sqlite3Strlen30(z); assert( p->current.anEq[i] );