diff --git a/manifest b/manifest index 42a11a725c..d311cdbbf3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sanalyze_as_needed\spragma\snow\sresponds\sto\stable\ssize\sgrowth\sand\swill\nautomatically\srerun\sthe\sanalysis\safter\seach\s10x\ssize\sincrease. -D 2017-02-17T19:24:06.618 +C In\sthe\sanalyze_as_needed\spragma,\savoid\srunning\sunnecessary\sOP_LoadAnalysis\s\nand\sOP_Expire\sopcodes.\s\sMake\sthe\sanalyze_as_needed\spragma\sresponsive\sto\sthe\nschema\sname. +D 2017-02-18T02:19:02.183 F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc a89ea37ab5928026001569f056973b9059492fe2 @@ -331,7 +331,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121 -F src/analyze.c acef9c48eac30438e82f39eb8df6682c6e33942e +F src/analyze.c eb50045b8f2e0d8a0a36a2158a65afe098d9a3bb F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43 F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792 F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b @@ -383,11 +383,11 @@ F src/os_win.c cf90abd4e50d9f56d2c20ce8e005aff55d7bd8e9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa -F src/parse.y d5695ae4887a52352b1b8a3e3623477c7e79abeb +F src/parse.y 591704fce84f814d9a3642774c1f011d38f4149c F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953 -F src/pragma.c e8b2ea66dfb1b90c53b920c08914ac26b109053a +F src/pragma.c cf0f101d2986d258699cbbd249392858ec9a6b7e F src/pragma.h 065e184494f12e94111da1ab6984faa7b6142e68 F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a F src/printf.c 67427bbee66d891fc6f6f5aada857e9cdb368c1c @@ -399,7 +399,7 @@ F src/shell.c bb8e20789499aec921a01d8744c616b81b8214f1 F src/sqlite.h.in 751ff125eb159c8f92c182b8df980a5e4f50e966 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae -F src/sqliteInt.h 60c38b84a796cc9d0a9a794cca254b09898b9cc5 +F src/sqliteInt.h 70abfa92e02688f1d189bf63fd25d309ca8d8d1e F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -1557,7 +1557,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 e93db2373127d31d33ec46ef918fa9386bb664a6 -R 484e61dbf95be1098adb3acfa069e723 +P bfbdd07409688fac4ccddbab3639745f6152e23d +R 1c1b7451b307830f90322e6d51007af7 U drh -Z 81466028927592a195c5763d3460fcde +Z 2d7c806c83a06bb426974433c00a5916 diff --git a/manifest.uuid b/manifest.uuid index 8be7eeb5b9..9825130b6a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bfbdd07409688fac4ccddbab3639745f6152e23d \ No newline at end of file +882599a4a7ea92c9e7752e0745475508e58a11c3 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 082713fd23..c30027aec9 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -971,6 +971,7 @@ static void analyzeOneTable( int jZeroRows = -1; /* Jump from here if number of rows is zero */ int iDb; /* Index of database containing pTab */ u8 needTableCnt = 1; /* True to count the table */ + int regWorkDone = iMem++; /* Set to 1 if any work is done */ int regNewRowid = iMem++; /* Rowid for the inserted record */ int regStat4 = iMem++; /* Register to hold Stat4Accum object */ int regChng = iMem++; /* Index of changed index field */ @@ -1018,7 +1019,7 @@ static void analyzeOneTable( sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); if( szOld>0 ){ addrSizeCk = sqlite3VdbeAddOp3(v, OP_IfSmaller, iTabCur, 0, szOld); - } + } sqlite3VdbeLoadString(v, regTabname, pTab->zName); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ @@ -1276,21 +1277,11 @@ static void analyzeOneTable( sqlite3VdbeChangeP5(v, OPFLAG_APPEND); sqlite3VdbeJumpHere(v, jZeroRows); } + sqlite3VdbeAddOp2(v, OP_Integer, 1, regWorkDone); + VdbeComment((v, "work was done")); sqlite3VdbeJumpHere(v, addrSizeCk); } - -/* -** Generate code that will cause the most recent index analysis to -** be loaded into internal hash tables where is can be used. -*/ -static void loadAnalysis(Parse *pParse, int iDb){ - Vdbe *v = sqlite3GetVdbe(pParse); - if( v ){ - sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb); - } -} - /* ** Return true if table pTab might need to being reanalyzed. Return ** false if we know that pTab should not be reanalyzed. @@ -1322,54 +1313,70 @@ static int analyzeNeeded(Table *pTab, LogEst *pThreshold){ } /* -** Generate code that will do an analysis of an entire database. +** Generate code that will do an analysis of an entire database, or +** all databases in the connection if iDbReq is negative. ** -** Return a count of the number of tables actually analyzed. Return 0 -** if nothing was analyzed. +** If onlyIfNeeded is true, then only run the analysis if SQLite thinks +** it is actually needed. */ -static int analyzeDatabase(Parse *pParse, int iDbReq, int onlyIfNeeded){ +void sqlite3AnalyzeDatabase( + Parse *pParse, /* The parsing context */ + int iDbReq, /* Which schema to analyze. -1 for all (except TEMP) */ + int onlyIfNeeded /* Only do the analysis if needed, when true */ +){ sqlite3 *db = pParse->db; Schema *pSchema; HashElem *k; - int iStatCur; - int iMem; - int iTab; + int iStatCur = 0; + int iMem = 0; + int iTab = 0; int iDb; /* Database currently being analyzed */ int iDbFirst, iDbLast; /* Range of databases to be analyzed */ - int cnt; /* Number of tables analyzed in a single database */ - int allCnt = 0; /* Number of tables analyzed across all databases */ + int bStatTabs = 0; + Vdbe *v = sqlite3GetVdbe(pParse); + int nHit = 0; + unsigned char aHit[SQLITE_MAX_ATTACHED+2]; + if( v==0 ) return; if( iDbReq>=0 ){ iDbFirst = iDbLast = iDbReq; }else{ iDbFirst = 0; iDbLast = db->nDb-1; } - for(iDb=iDbFirst; iDb<=iDbLast; iDb++){ + for(iDb=iDbFirst; iDb<=iDbLast; iDb++, bStatTabs=0){ if( iDb==1 ) continue; /* Do not analyze the TEMP database */ pSchema = db->aDb[iDb].pSchema; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); - cnt = 0; for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); LogEst szThreshold = 0; if( !onlyIfNeeded || analyzeNeeded(pTab, &szThreshold) ){ - if( cnt==0 ){ - sqlite3BeginWriteOperation(pParse, 0, iDb); + if( iMem==0 ){ iStatCur = pParse->nTab; pParse->nTab += 3; - openStatTable(pParse, iDb, iStatCur, 0, 0); iMem = pParse->nMem+1; iTab = pParse->nTab; + sqlite3VdbeAddOp2(v, OP_Integer, 0, iMem); + } + if( !bStatTabs ){ + aHit[nHit++] = iDb; + sqlite3BeginWriteOperation(pParse, 0, iDb); + openStatTable(pParse, iDb, iStatCur, 0, 0); + bStatTabs = 1; } analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab, szThreshold); - cnt++; - allCnt++; } } - if( cnt ) loadAnalysis(pParse, iDb); } - return allCnt; + if( iMem ){ + int addrTop = sqlite3VdbeAddOp1(v, OP_IfNot, iMem); VdbeCoverage(v); + for(iDb=0; iDbdb) ); @@ -1392,9 +1400,13 @@ static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){ }else{ openStatTable(pParse, iDb, iStatCur, pTab->zName, "tbl"); } - analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur,pParse->nMem+1, + analyzeOneTable(pParse, pTab, pOnlyIdx, iStatCur, pParse->nMem+1, pParse->nTab, 0); - loadAnalysis(pParse, iDb); + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp1(v, OP_LoadAnalysis, iDb); + sqlite3VdbeAddOp0(v, OP_Expire); + } } /* @@ -1414,15 +1426,13 @@ static void analyzeTable(Parse *pParse, Table *pTab, Index *pOnlyIdx){ ** are believed to be in need of analysis. The conditional analysis ** might well be a no-op. */ -void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2, int ifNeeded){ +void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){ sqlite3 *db = pParse->db; int iDb; char *z, *zDb; Table *pTab; Index *pIdx; Token *pTableName; - Vdbe *v; - int needExpire = 1; /* Read the database schema. If an error occurs, leave an error message ** and code in pParse and return NULL. */ @@ -1434,12 +1444,12 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2, int ifNeeded){ assert( pName2!=0 || pName1==0 ); if( pName1==0 ){ /* Form 1: Analyze everything */ - needExpire = analyzeDatabase(pParse, -1, ifNeeded) || ifNeeded==0; + sqlite3AnalyzeDatabase(pParse, -1, 0); }else if( pName2->n==0 ){ /* Form 2: Analyze the database or table named */ iDb = sqlite3FindDb(db, pName1); if( iDb>=0 ){ - analyzeDatabase(pParse, iDb, 0); + sqlite3AnalyzeDatabase(pParse, iDb, 0); }else{ z = sqlite3NameFromToken(db, pName1); if( z ){ @@ -1467,10 +1477,6 @@ void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2, int ifNeeded){ } } } - if( needExpire ){ - v = sqlite3GetVdbe(pParse); - if( v ) sqlite3VdbeAddOp0(v, OP_Expire); - } } /* diff --git a/src/parse.y b/src/parse.y index ff03c128ac..9cada2a1be 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1512,8 +1512,8 @@ cmd ::= REINDEX nm(X) dbnm(Y). {sqlite3Reindex(pParse, &X, &Y);} /////////////////////////////////// ANALYZE /////////////////////////////////// %ifndef SQLITE_OMIT_ANALYZE -cmd ::= ANALYZE. {sqlite3Analyze(pParse, 0, 0, 0);} -cmd ::= ANALYZE nm(X) dbnm(Y). {sqlite3Analyze(pParse, &X, &Y, 0);} +cmd ::= ANALYZE. {sqlite3Analyze(pParse, 0, 0);} +cmd ::= ANALYZE nm(X) dbnm(Y). {sqlite3Analyze(pParse, &X, &Y);} %endif //////////////////////// ALTER TABLE table ... //////////////////////////////// diff --git a/src/pragma.c b/src/pragma.c index 789751958c..3bcf62f69f 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1832,7 +1832,7 @@ void sqlite3Pragma( ** PRAGMA analyze_as_needed */ case PragTyp_ANALYZE_AS_NEEDED: { - sqlite3Analyze(pParse, 0, 0, 1); + sqlite3AnalyzeDatabase(pParse, zDb ? iDb : -1, 1); break; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d9cad11bcf..218c2c6af6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4027,7 +4027,8 @@ void sqlite3AlterFinishAddColumn(Parse *, Token *); void sqlite3AlterBeginAddColumn(Parse *, SrcList *); CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*); char sqlite3AffinityType(const char*, u8*); -void sqlite3Analyze(Parse*, Token*, Token*, int); +void sqlite3Analyze(Parse*, Token*, Token*); +void sqlite3AnalyzeDatabase(Parse*,int,int); int sqlite3InvokeBusyHandler(BusyHandler*); int sqlite3FindDb(sqlite3*, Token*); int sqlite3FindDbName(sqlite3 *, const char *);