From: drh Date: Wed, 18 Mar 2020 14:43:05 +0000 (+0000) Subject: Add the SQLITE_ANALYZE_LIMIT compile-time option (expected to be temporary) X-Git-Tag: version-3.32.0~49^2~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=59a8cb79316815f4eeb48e17252723df39589dda;p=thirdparty%2Fsqlite.git Add the SQLITE_ANALYZE_LIMIT compile-time option (expected to be temporary) that sets a threshold at which ANALYZE starts to use approximations during the analysis process. FossilOrigin-Name: a773fd4698d474fda5e57bc77ed66a79cf74efee2706f43f6def6f450bfd1fc0 --- diff --git a/manifest b/manifest index 0d201b4bd7..411043d48a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Provide\san\sestimated\srow\scount\sto\sstat_init()\sfor\sSTAT1\sanalysis. -D 2020-03-17T17:11:23.756 +C Add\sthe\sSQLITE_ANALYZE_LIMIT\scompile-time\soption\s(expected\sto\sbe\stemporary)\nthat\ssets\sa\sthreshold\sat\swhich\sANALYZE\sstarts\sto\suse\sapproximations\sduring\nthe\sanalysis\sprocess. +D 2020-03-18T14:43:05.229 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -466,7 +466,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c f48a4423c8f198d7f1ae4940f74b606707d05384ac79fb219be8e3323af2a2de -F src/analyze.c 0df49eed25e472ef00bfe12184548a5a51890e7cd650c40fe2681430bdcae9d1 +F src/analyze.c 2ae3d2e13387eac29ffb4f94279e00ec1f96145f56a06a8aa57533bd0c64bd99 F src/attach.c fa5addce233a2bb2dfdefeee3b37000e154c47214d3269cab1bb331416e330db F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 F src/backup.c 5e617c087f1c2d6005c2ec694ce80d6e16bc68d906e1b1c556d7c7c2228b636b @@ -1860,7 +1860,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a9bfa47aeea27e91611ba913d33e6635d2016e2c2ab78f9b0657f1bd8933e1a8 -R 83170381358df6124fa4b6f4f7b0bc2e +P 714419fe85cfdad22979183a94e4569c87740652758ab76b646753cf2b013b54 +R 9e076c207b1e065d9ce5cb1bfdf9885a U drh -Z b22aba55e2c8d6bfe6ccc85eac867e5f +Z 74d44bcaa72564678d221e098ce4dbd2 diff --git a/manifest.uuid b/manifest.uuid index 73b2e21252..df0df117b5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -714419fe85cfdad22979183a94e4569c87740652758ab76b646753cf2b013b54 \ No newline at end of file +a773fd4698d474fda5e57bc77ed66a79cf74efee2706f43f6def6f450bfd1fc0 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index a7f70102b1..7290deae19 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -284,6 +284,7 @@ struct StatAccum { tRowcnt nRow; /* Number of rows visited so far */ int nCol; /* Number of columns in index + pk/rowid */ int nKeyCol; /* Number of index columns w/o the pk/rowid */ + u8 nSkipAhead; /* Number of times of skip-ahead */ StatSample current; /* Current row as a StatSample */ #ifdef SQLITE_ENABLE_STAT4 tRowcnt nPSample; /* How often to do a periodic sample */ @@ -404,10 +405,10 @@ static void statInit( int nKeyCol; /* Number of key columns */ int nColUp; /* nCol rounded up for alignment */ int n; /* Bytes of space to allocate */ - sqlite3 *db; /* Database connection */ + sqlite3 *db = sqlite3_context_db_handle(context); /* Database connection */ #ifdef SQLITE_ENABLE_STAT4 /* Maximum number of samples. 0 if STAT4 data is not collected */ - int mxSample = sqlite3_value_int64(argv[2]) ? SQLITE_STAT4_SAMPLES : 0; + int mxSample = OptimizationEnabled(db,SQLITE_Stat4) ?SQLITE_STAT4_SAMPLES :0; #endif /* Decode the three function arguments */ @@ -442,16 +443,17 @@ static void statInit( p->nRow = 0; p->nCol = nCol; p->nKeyCol = nKeyCol; + p->nSkipAhead = 0; p->current.anDLt = (tRowcnt*)&p[1]; p->current.anEq = &p->current.anDLt[nColUp]; #ifdef SQLITE_ENABLE_STAT4 + p->mxSample = mxSample; if( mxSample ){ u8 *pSpace; /* Allocated space not yet assigned */ int i; /* Used to iterate through p->aSample[] */ p->iGet = -1; - p->mxSample = mxSample; p->nPSample = (tRowcnt)(p->nEst/(mxSample/3+1) + 1); p->current.anLt = &p->current.anEq[nColUp]; p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]); @@ -675,6 +677,15 @@ static void samplePushPrevious(StatAccum *p, int iChng){ } #endif /* SQLITE_ENABLE_STAT4 */ +/* +** A limit on the number of rows of an index that will be examined +** by ANALYZE before it starts going with approximations. Zero means +** "no limit". +*/ +#ifndef SQLITE_ANALYZE_LIMIT +# define SQLITE_ANALYZE_LIMIT 0 +#endif + /* ** Implementation of the stat_push SQL function: stat_push(P,C,R) ** Arguments: @@ -684,10 +695,13 @@ static void samplePushPrevious(StatAccum *p, int iChng){ ** R Rowid for the current row. Might be a key record for ** WITHOUT ROWID tables. ** -** This SQL function always returns NULL. It's purpose it to accumulate -** statistical data and/or samples in the StatAccum object about the -** index being analyzed. The stat_get() SQL function will later be used to -** extract relevant information for constructing the sqlite_statN tables. +** The purpose of this routine is to collect statistical data and/or +** samples from the index being analyzed into the StatAccum object. +** The stat_get() SQL function will be used afterwards to +** retrieve the information gathered. +** +** This SQL function usually returns NULL, but might return an integer +** if it wants the byte-code to do special processing. ** ** The R parameter is only used for STAT4 */ @@ -729,6 +743,7 @@ static void statPush( p->current.anEq[i] = 1; } } + p->nRow++; #ifdef SQLITE_ENABLE_STAT4 if( p->mxSample ){ @@ -757,9 +772,16 @@ static void statPush( sampleCopy(p, &p->aBest[i], &p->current); } } + }else +#endif +#if SQLITE_ANALYZE_LIMIT + if( p->nRow>SQLITE_ANALYZE_LIMIT*(p->nSkipAhead+1) ){ + p->nSkipAhead++; + sqlite3_result_int(context, p->current.anDLt[0]>0); } #endif } + static const FuncDef statPushFuncdef = { 2+IsStat4, /* nArg */ SQLITE_UTF8, /* funcFlags */ @@ -847,7 +869,8 @@ static void statGet( return; } - sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow); + sqlite3_snprintf(24, zRet, "%llu", + p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow); z = zRet + sqlite3Strlen30(zRet); for(i=0; inKeyCol; i++){ u64 nDistinct = p->current.anDLt[i] + 1; @@ -1204,9 +1227,18 @@ static void analyzeOneTable( } #endif assert( regChng==(regStat+1) ); - sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4, - &statPushFuncdef, 0); - sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); + { + int j1, j2, j3; + sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4, + &statPushFuncdef, 0); + j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regTemp); + j2 = sqlite3VdbeAddOp1(v, OP_If, regTemp); + j3 = sqlite3VdbeAddOp4Int(v, OP_SeekGT, iIdxCur, 0, regPrev, 1); + sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v); + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeJumpHere(v, j3); + } /* Add the entry to the stat1 table. */ callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1);