-C Modify\sthe\sANALYZE\scommand\sto\sstore\sworst-case\sstatistics\sin\ssqlite_stat1,\nrather\sthn\saverage\scase.
-D 2016-02-29T18:30:30.116
+C The\sANALYZE\scommand\sautomatically\sappends\s"noskipscan"\sto\ssqlite_stat1\sentries\nthat\shave\slarge\sworst-case\srepeat\sestimates\sbut\ssmall\saverage\srepeat\sestimates.
+D 2016-02-29T21:27:16.923
F Makefile.in 4e90dc1521879022aa9479268a4cd141d1771142
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 4f319afb7c049d40aff7af6e8c4e7cc2ba18e079
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 44e18dfd78e8942d65d3cdaec4de972b5cd9f1f2
-F src/analyze.c 37343619c6c560722aac521d156d34ebff746526
+F src/analyze.c 95b2e37e92cbeb9093700b8248e1ec73b3da417b
F src/attach.c a3724c64de1099d85e30751213d285752aed9505
F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce
F src/sqlite.h.in 57d2a02b14c9ec4f7cb294153eaf62294dc5aa68
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h dfbe62ffd95b99afe2140d8c35b180d11924072d
-F src/sqliteInt.h 01b43972162c2b5ed864060a23502af3abe0e4f4
+F src/sqliteInt.h e05c48a2b90836452d47d03b2c90a7b7ec9f8ba4
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
F src/wal.c 10deb6b43887662691e5f53d10b3c171c401169b
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
-F src/where.c 32051597188dc632bafb32d50a9c3a04fb97ce39
+F src/where.c 2786a5f385dedd67e9cedaa00645bf44444f3c68
F src/whereInt.h 93297d56edd137b7ea004490690fb6e2ce028a34
F src/wherecode.c 39c1ef4598bedf1d66249334c74efd23ddd182ac
F src/whereexpr.c fb87944b1254234e5bba671aaf6dee476241506a
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P c9a30e117f2c6c9ef0cc0c6ca5227d2961715b8f
-R 180de557065fd2bddac753825b6be69a
-T *branch * analyze-worst-case
-T *sym-analyze-worst-case *
-T -sym-trunk *
+P 5a0143c94ec0682798f3c09fba63593e695d2e2d
+R 177b6cf14f8f11e0a114dc66d2d822d0
U drh
-Z 3d046dcd3035333c5259dea36a77e4b0
+Z ca3d3ef3ca17a24048e080e522e9cbee
-5a0143c94ec0682798f3c09fba63593e695d2e2d
\ No newline at end of file
+6326ba5891fae9c6be0c0c51cebcbe44c9f3f057
\ No newline at end of file
n = sizeof(*p)
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.amxEq */
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */
+ sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */
+ sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
p->nKeyCol = nKeyCol;
p->current.anEq = (tRowcnt*)&p[1];
p->current.amxEq = &p->current.anEq[nColUp];
+ p->current.anDLt = &p->current.amxEq[nColUp];
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
{
p->iGet = -1;
p->mxSample = mxSample;
p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
- 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]);
p->current.anEq[i]++;
}
for(i=iChng; i<p->nCol; i++){
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
p->current.anDLt[i]++;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
p->current.anLt[i] += p->current.anEq[i];
#endif
p->current.anEq[i] = 1;
** * "WHERE a=? AND b=?" matches 2 rows.
**
** Use the worst-case estimate: the maximum number of repeated entries
- ** in the index.
+ ** in the index. The worst-case estimate is best for picking indexes.
+ ** But for skip-scan, we want an average case estimate. The worst-case
+ ** estimate might be too high. To avoid undesirable skip-scans, if the
+ ** worst-case estimate is above the WHERE_SKIPSCAN_ONSET but the average
+ ** estimate is below, simply disable skipscans on this index by adding
+ ** the "noskipscan" modifier onto the end of the stat line.
*/
char *z;
int i;
+ int noSkipScan = 0;
- char *zRet = sqlite3MallocZero( (p->nKeyCol+1)*25 );
+ char *zRet = sqlite3MallocZero( (p->nKeyCol+2)*25 );
if( zRet==0 ){
sqlite3_result_error_nomem(context);
return;
sqlite3_snprintf(24, z, " %llu", iVal);
z += sqlite3Strlen30(z);
assert( p->current.anEq[i] );
+ if( i>0 && iVal>=WHERE_SKIPSCAN_ONSET+5 ){
+ iVal = p->current.anDLt[i];
+ iVal = (p->nRow + iVal)/(iVal + 1);
+ if( iVal<WHERE_SKIPSCAN_ONSET-5 ) noSkipScan = 1;
+ }
}
- assert( z[0]=='\0' && z>zRet );
-
+ if( noSkipScan ) sqlite3_snprintf(14, z, " noskipscan");
sqlite3_result_text(context, zRet, -1, sqlite3_free);
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
#define JT_OUTER 0x0020 /* The "OUTER" keyword is present */
#define JT_ERROR 0x0040 /* unknown or unsupported join type */
+/*
+** TUNING: The skip-scan optimization is only profitable if the average
+** number of repeats of an entry in the index is greater than or equal to
+** WHERE_SKIPSCAN_ONSET. If the average numbe of repeats is less
+** than WHERE_SKIPSCAN_ONSET, then it is faster to do a full table
+** scan.
+*/
+#define WHERE_SKIPSCAN_ONSET 18
+#define WHERE_SKIPSCAN_ONSET_LOG 42
/*
** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin()
** the code). And, even if it is not, it should not be too much slower.
** On the other hand, the extra seeks could end up being significantly
** more expensive. */
- assert( 42==sqlite3LogEst(18) );
+ assert( WHERE_SKIPSCAN_ONSET_LOG==sqlite3LogEst(WHERE_SKIPSCAN_ONSET) );
if( saved_nEq==saved_nSkip
&& saved_nEq+1<pProbe->nKeyCol
&& pProbe->noSkipScan==0
- && pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
+ && pProbe->aiRowLogEst[saved_nEq+1]>=WHERE_SKIPSCAN_ONSET_LOG
&& (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
){
LogEst nIter;