Simplifications to PRAGMA optimize to make it easier to use. It always

tries to ANALYZE unanalyzed indexes.  The 0x10000 flag just makes it check
for size changes in all tables.

FossilOrigin-Name: 44ed7f4cd07a88a2fdd303a2c78e6babe01d7344b399bd2b80ed68d75a77aaa2
This commit is contained in:
drh 2024-02-19 13:50:09 +00:00
parent 9f34a05e98
commit 6c6356f7f2
3 changed files with 61 additions and 38 deletions

View File

@ -1,5 +1,5 @@
C Change\sthe\s0x20000\sbit\s(use\sanalysis\slimit)\sto\s0x10,\smeaning\sthat\sthis\sfeature\nis\son\sby\sdefault.\s\sThe\sdefault\sanalysis\slimit\sis\schanged\sto\s2000\swhich\sis\nalmost\salways\ssufficient\sfor\saccurate\sanalysis\sresults. C Simplifications\sto\sPRAGMA\soptimize\sto\smake\sit\seasier\sto\suse.\s\sIt\salways\ntries\sto\sANALYZE\sunanalyzed\sindexes.\s\sThe\s0x10000\sflag\sjust\smakes\sit\scheck\nfor\ssize\schanges\sin\sall\stables.
D 2024-02-19T13:06:27.586 D 2024-02-19T13:50:09.987
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -732,7 +732,7 @@ F src/parse.y bfd6da46fc895cd8237400ff485d04ab0b32e47eb56de20982bb7f53e56c1f42
F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75 F src/pcache.c 040b165f30622a21b7a9a77c6f2e4877a32fb7f22d4c7f0d2a6fa6833a156a75
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5 F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00 F src/pcache1.c 602acb23c471bb8d557a6f0083cc2be641d6cafcafa19e481eba7ef4c9ca0f00
F src/pragma.c b877efa88ea41560ee5dd95daa30c8cadb743381c59b8921a5143bf0792c6e3b F src/pragma.c 9197331dd283a6010bb4e2c129a9015f854203d27fa6fbe89e1aea742b78351c
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7 F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c F src/prepare.c 371f6115cb69286ebc12c6f2d7511279c2e47d9f54f475d46a554d687a3b312c
F src/printf.c 18fbdf028345c8fbe6044f5f5bfda5a10d48d6287afef088cc21b0ca57985640 F src/printf.c 18fbdf028345c8fbe6044f5f5bfda5a10d48d6287afef088cc21b0ca57985640
@ -2162,8 +2162,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P d13b79eae6df7f9d1f3b8062ddc75a12ff038196b3d752d2672a9925fa45ca56 P 4abd47b5917099a2f74e53e12c987da0722304a5e9a93b6d43015c1f45c48444
R e258fa6228ef566d2b5670b2822a20d1 R 39db09ba2f5384fee677814cc2cbe4fe
U drh U drh
Z e864b92d6fb5e0c6f09ca55fa83dd960 Z cf23276671f3baaf4e4f3579488af586
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
4abd47b5917099a2f74e53e12c987da0722304a5e9a93b6d43015c1f45c48444 44ed7f4cd07a88a2fdd303a2c78e6babe01d7344b399bd2b80ed68d75a77aaa2

View File

@ -2425,11 +2425,15 @@ void sqlite3Pragma(
** currently (2024-02-19) set to 2000, which is such that ** currently (2024-02-19) set to 2000, which is such that
** the worst case run-time for PRAGMA optimize on a 100MB ** the worst case run-time for PRAGMA optimize on a 100MB
** database will usually be less than 100 milliseconds on ** database will usually be less than 100 milliseconds on
** a RaspberryPI-4 class machine. Off by default. ** a RaspberryPI-4 class machine. On by default.
**
** 0x00020 Run ANALYZE on any table that has a complete index
** (an index without a WHERE clause) that lacks an entry
** in the sqlite_stat1 table. On by default.
** **
** 0x10000 Look at tables to see if they need to be reanalyzed ** 0x10000 Look at tables to see if they need to be reanalyzed
** even if they have not been queried during the current ** due to growth or shrinkage even if they have not been
** connection. Off by default. ** queried during the current connection. Off by default.
** **
** The default MASK is and always shall be 0x0fffe. In the current ** The default MASK is and always shall be 0x0fffe. In the current
** implementation, the default mask only covers the 0x00002 optimization, ** implementation, the default mask only covers the 0x00002 optimization,
@ -2444,18 +2448,25 @@ void sqlite3Pragma(
** **
** (1) MASK bit 0x00002 is set. ** (1) MASK bit 0x00002 is set.
** **
** (2) Either the 0x10000 MASK bit is set or else the query planner used ** (2) The table is an ordinary table, not a virtual table or view.
** sqlite_stat1-style statistics for one or more indexes of the table
** at some point during the lifetime of the current connection.
** **
** (3) One or more indexes of the table are currently unanalyzed OR ** (3) The table name does not begin with "sqlite_".
** the number of rows in the table has increased or decreased by
** 10-fold (the new size is either greater than 10 times the old
** size or less than 1/10th of the old size).
** **
** (4) The table is an ordinary table, not a virtual table or view. ** (4) One or more of the following is true:
** (4a) The 0x10000 MASK bit is set.
** (4b) One or more complete indexes on the table lacks an entry
** in the sqlite_stat1 table.
** (4c) The query planner used sqlite_stat1-style statistics for one
** or more indexes of the tableat some point during the lifetime
** of the current connection.
** **
** (5) The table name does not begin with "sqlite_". ** (5) One or more of the following is true:
** (5a) One or mroe complete indexes on the table lacks an entry
** in the sqlite_stat1 table. (Same as 4a)
** (5b) The number of rows in the table has increased or decreased by
** 10-fold. In other words, the current size of the table is
** 10 times larger than the size in sqlite_stat1 or else the
** current size is less than 1/10th the size in sqlite_stat1.
** **
** The rules for when tables are analyzed are likely to change in ** The rules for when tables are analyzed are likely to change in
** future releases. Future versions of SQLite might accept a string ** future releases. Future versions of SQLite might accept a string
@ -2473,7 +2484,7 @@ void sqlite3Pragma(
char *zSubSql; /* SQL statement for the OP_SqlExec opcode */ char *zSubSql; /* SQL statement for the OP_SqlExec opcode */
u32 opMask; /* Mask of operations to perform */ u32 opMask; /* Mask of operations to perform */
int nLimit; /* Analysis limit to use */ int nLimit; /* Analysis limit to use */
int once = 0; /* One-time initialization done */ int nCheck = 0; /* Number of tables to be optimized */
if( zRight ){ if( zRight ){
opMask = (u32)sqlite3Atoi(zRight); opMask = (u32)sqlite3Atoi(zRight);
@ -2503,30 +2514,42 @@ void sqlite3Pragma(
/* Do not scan system tables */ /* Do not scan system tables */
if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ) continue; if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ) continue;
/* If table pTab has not been used in a way that would benefit from /* Find the size of the table as last recorded in sqlite_stat1.
** having analysis statistics during the current session, then skip it, ** If any complete index (index without a WHERE clause) is unanalyzed,
** unless the 0x10000 MASK bit is set. */ ** then the threshold is -1 to indicate a new, unanalyzed index
if( (pTab->tabFlags & TF_MaybeReanalyze)==0 */
&& (opMask & 0x10000)==0
){
continue;
}
/* Hold a write transaction open for efficiency */
if( !once || 1 ){
sqlite3BeginWriteOperation(pParse, 0, iDb);
once = 1;
}
/* Reanalyze if the table is 10 times larger or smaller than
** the last analysis */
szThreshold = pTab->nRowLogEst; szThreshold = pTab->nRowLogEst;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
if( !pIdx->hasStat1 ){ if( !pIdx->hasStat1 && pIdx->pPartIdxWhere==0 ){
szThreshold = -1; /* Always analyze if any index lacks statistics */ szThreshold = -1; /* Always analyze if any index lacks statistics */
break; break;
} }
} }
/* If table pTab has not been used in a way that would benefit from
** having analysis statistics during the current session, then skip it,
** unless the 0x10000 MASK bit is set. */
if( (pTab->tabFlags & TF_MaybeReanalyze)!=0 ){
/* Check for size change if stat1 has been used for a query */
}else if( opMask & 0x10000 ){
/* Check for size change if 0x10000 is set */
}else if( pTab->pIndex!=0 && szThreshold<0 ){
/* Do analysis if unanalyzed complete indexes exists */
}else{
/* Otherwise, we can skip this table */
continue;
}
nCheck++;
if( nCheck==2 ){
/* If ANALYZE might be invoked two or more times, hold a write
** transaction for efficiency */
sqlite3BeginWriteOperation(pParse, 0, iDb);
}
/* Reanalyze if the table is 10 times larger or smaller than
** the last analysis. Unconditional reanalysis if there are
** unanalyzed complete indexes. */
if( szThreshold>=0 ){ if( szThreshold>=0 ){
LogEst iRange = 33; /* 10x size change */ LogEst iRange = 33; /* 10x size change */
sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); sqlite3OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead);