Improvements to the min/max optimization. Fix for a performance
regression introduced at [b8ba2f17f938c035] reported by [forum:/forumpost/4050026ab8|forum post 4050026ab8] FossilOrigin-Name: 249a71cc6822d6bdd5bb9e727aac81c6549693b418e9c0987b96850ee332c940
This commit is contained in:
commit
41d01407ea
23
manifest
23
manifest
@ -1,5 +1,5 @@
|
||||
C cli:\sOmit\ssurplus\swhitespace\sat\sthe\send\sof\slines\sin\s.explain\soutput.
|
||||
D 2021-01-13T12:59:20.834
|
||||
C Improvements\sto\sthe\smin/max\soptimization.\s\sFix\sfor\sa\sperformance\nregression\sintroduced\sat\s[b8ba2f17f938c035]\sreported\sby\n[forum:/forumpost/4050026ab8|forum\spost\s4050026ab8]
|
||||
D 2021-01-14T20:57:47.228
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -504,7 +504,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c c5e0c25cfb9960d9b7d49043de6adc12748853bc6dea76f5adef059e366f2f70
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 8c9c8cd2bd8eecdb06d9b6e89de7e9e65bae45cc8fc33609cc74023a5c296067
|
||||
F src/main.c 97e9f137354bc1f76dc9bb60a0a24f8c45cf73b33e80d3ee4c64155336fb820d
|
||||
F src/main.c 1c5de7b3fabcdf05f4fe563aab5d81d175b89c67a8678a12ba86629356afa356
|
||||
F src/malloc.c c1af4ac5a463648cd2953fd4ac679b3ba9022ce5ec794a60806150ad69dfd33a
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@ -535,17 +535,17 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
|
||||
F src/pragma.c 6daaaecc26a4b09481d21722525b079ce756751a43a79cc1d8f122d686806193
|
||||
F src/pragma.h 8dc78ab7e9ec6ce3ded8332810a2066f1ef6267e2e03cd7356ee00276125c6cf
|
||||
F src/prepare.c cfe5a0ec9fd612c89b4d50acfd4b796bd5fe850441cab0d866d72fa3aa982c45
|
||||
F src/prepare.c f288cbc35f79eb32e162de7e80a63ebe00d80e639dcfac071bee11570cbdb16f
|
||||
F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 1948a92ca9eab776632816b97e57c61d933474a78aad4f4ef835c916a83dbb1c
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c 74655feb1ba3767f0f376029acdf1e488942e6b02aa0e65679a75181c2fbe88f
|
||||
F src/shell.c.in 8331e564cd73e1784dd034d88ce626d2867531e9cc38ece980b256b09eb548b3
|
||||
F src/select.c 738cb746189f721f59972993c13085fa2975c4cbfd04ba26445f3b42c81237dc
|
||||
F src/shell.c.in 9ebc74e4f05cfbd0f4a36060fdaeff1da4e9af4458358722bc08c5a1ab9a0879
|
||||
F src/sqlite.h.in 0af968a1fa3c717261e1df0ed105fa7bddb4d82de7e0adb3eab49e6aa81b4de7
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
|
||||
F src/sqliteInt.h c7c7e0e79769885a1c7fa519299bdb222e83e2d7d4843ed6ca1cd9a585016386
|
||||
F src/sqliteInt.h 6aad58a5ae1374e18ea53d0c3ea71f047b67313426767783bd7fa14ee786725a
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@ -627,7 +627,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 69e770e96fd56cc21608992bf2c6f1f3dc5cf2572d0495c6a643b06c3a679f14
|
||||
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
||||
F src/walker.c d9c4e454ebb9499e908aa62d55b8994c375cf5355ac78f60d45af17f7890701c
|
||||
F src/where.c 3d31871d03906312d7d71a9c0b28c97bcbaead7606dfc15f9b3d080b18702385
|
||||
F src/where.c 0e6abb22a2323fec80b450825593c26a2ad8f4815d1ee3af9969d8f6144bf681
|
||||
F src/whereInt.h 9a3f577619f07700d16d89eeb2f3d94d6b7ed7f109c2dacf0ce8844921549506
|
||||
F src/wherecode.c a3a1aff30fe99a818d8e7c607980f033f40c68d890e03ed25838b9dbb7908bee
|
||||
F src/whereexpr.c 3a463e156ea388083c501502229c2c7f4f5c6b5330ea59bdf40d6eb6e155a25f
|
||||
@ -1895,7 +1895,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P db0ecfe66433f8915b6eb16d3735a4a0d0f8e0bbc395bc9c1364387506fc4657
|
||||
R 2ad612629a79dbad03e8b7f173945d59
|
||||
P 11e4eb095746602961a178044809a68a77ba7b367596997bef726e54062423d9 ccd3bae14b6b47bb0f9622700c04db989f76ce65e10e0709964cfd0675eca762
|
||||
R 3dc0d948d76c5e90d01be3a954f85921
|
||||
T +closed ccd3bae14b6b47bb0f9622700c04db989f76ce65e10e0709964cfd0675eca762
|
||||
U drh
|
||||
Z f407a95e341e109313c0922f7d2a229b
|
||||
Z 8ad13e36552647d99e513fed14d21def
|
||||
|
@ -1 +1 @@
|
||||
11e4eb095746602961a178044809a68a77ba7b367596997bef726e54062423d9
|
||||
249a71cc6822d6bdd5bb9e727aac81c6549693b418e9c0987b96850ee332c940
|
@ -4080,7 +4080,7 @@ int sqlite3_test_control(int op, ...){
|
||||
*/
|
||||
case SQLITE_TESTCTRL_OPTIMIZATIONS: {
|
||||
sqlite3 *db = va_arg(ap, sqlite3*);
|
||||
db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff);
|
||||
db->dbOptFlags = va_arg(ap, u32);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -571,10 +571,10 @@ void sqlite3ParserReset(Parse *pParse){
|
||||
pThis = pNext;
|
||||
}
|
||||
while( pParse->pCleanup ){
|
||||
ParseCleanup *pThis = pParse->pCleanup;
|
||||
pParse->pCleanup = pThis->pNext;
|
||||
pThis->xCleanup(db, pThis->pPtr);
|
||||
sqlite3DbFree(db, pThis);
|
||||
ParseCleanup *pCleanup = pParse->pCleanup;
|
||||
pParse->pCleanup = pCleanup->pNext;
|
||||
pCleanup->xCleanup(db, pCleanup->pPtr);
|
||||
sqlite3DbFree(db, pCleanup);
|
||||
}
|
||||
sqlite3DbFree(db, pParse->aLabel);
|
||||
if( pParse->pConstExpr ){
|
||||
|
14
src/select.c
14
src/select.c
@ -4640,7 +4640,11 @@ static u8 minMaxQuery(sqlite3 *db, Expr *pFunc, ExprList **ppMinMax){
|
||||
assert( *ppMinMax==0 );
|
||||
assert( pFunc->op==TK_AGG_FUNCTION );
|
||||
assert( !IsWindowFunc(pFunc) );
|
||||
if( pEList==0 || pEList->nExpr!=1 || ExprHasProperty(pFunc, EP_WinFunc) ){
|
||||
if( pEList==0
|
||||
|| pEList->nExpr!=1
|
||||
|| ExprHasProperty(pFunc, EP_WinFunc)
|
||||
|| OptimizationDisabled(db, SQLITE_MinMaxOpt)
|
||||
){
|
||||
return eRet;
|
||||
}
|
||||
zFunc = pFunc->u.zToken;
|
||||
@ -6773,7 +6777,7 @@ int sqlite3Select(
|
||||
/* End of the loop
|
||||
*/
|
||||
if( groupBySort ){
|
||||
sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx, addrTopOfLoop);
|
||||
sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
|
||||
VdbeCoverage(v);
|
||||
}else{
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
@ -6885,7 +6889,6 @@ int sqlite3Select(
|
||||
explainSimpleCount(pParse, pTab, pBest);
|
||||
}else{
|
||||
int regAcc = 0; /* "populate accumulators" flag */
|
||||
int addrSkip;
|
||||
|
||||
/* If there are accumulator registers but no min() or max() functions
|
||||
** without FILTER clauses, allocate register regAcc. Register regAcc
|
||||
@ -6934,9 +6937,8 @@ int sqlite3Select(
|
||||
}
|
||||
updateAccumulator(pParse, regAcc, pAggInfo);
|
||||
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
|
||||
addrSkip = sqlite3WhereOrderByLimitOptLabel(pWInfo);
|
||||
if( addrSkip!=sqlite3WhereContinueLabel(pWInfo) ){
|
||||
sqlite3VdbeGoto(v, addrSkip);
|
||||
if( minMaxFlag ){
|
||||
sqlite3WhereMinMaxOptEarlyOut(v, pWInfo);
|
||||
}
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
finalizeAggFunctions(pParse, pAggInfo);
|
||||
|
@ -9995,7 +9995,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
/* sqlite3_test_control(int, db, int) */
|
||||
case SQLITE_TESTCTRL_OPTIMIZATIONS:
|
||||
if( nArg==3 ){
|
||||
int opt = (int)strtol(azArg[2], 0, 0);
|
||||
unsigned int opt = (unsigned int)strtol(azArg[2], 0, 0);
|
||||
rc2 = sqlite3_test_control(testctrl, p->db, opt);
|
||||
isOk = 3;
|
||||
}
|
||||
|
@ -1496,7 +1496,7 @@ struct sqlite3 {
|
||||
int errCode; /* Most recent error code (SQLITE_*) */
|
||||
int errMask; /* & result codes with this before returning */
|
||||
int iSysErrno; /* Errno value from last system error */
|
||||
u16 dbOptFlags; /* Flags to enable/disable optimizations */
|
||||
u32 dbOptFlags; /* Flags to enable/disable optimizations */
|
||||
u8 enc; /* Text encoding */
|
||||
u8 autoCommit; /* The auto-commit flag. */
|
||||
u8 temp_store; /* 1: file 2: memory 0: default */
|
||||
@ -1703,24 +1703,25 @@ struct sqlite3 {
|
||||
** sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS,...) interface to
|
||||
** selectively disable various optimizations.
|
||||
*/
|
||||
#define SQLITE_QueryFlattener 0x0001 /* Query flattening */
|
||||
#define SQLITE_WindowFunc 0x0002 /* Use xInverse for window functions */
|
||||
#define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */
|
||||
#define SQLITE_FactorOutConst 0x0008 /* Constant factoring */
|
||||
#define SQLITE_DistinctOpt 0x0010 /* DISTINCT using indexes */
|
||||
#define SQLITE_CoverIdxScan 0x0020 /* Covering index scans */
|
||||
#define SQLITE_OrderByIdxJoin 0x0040 /* ORDER BY of joins via index */
|
||||
#define SQLITE_Transitive 0x0080 /* Transitive constraints */
|
||||
#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
|
||||
#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
|
||||
#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
|
||||
#define SQLITE_Stat4 0x0800 /* Use STAT4 data */
|
||||
/* TH3 expects the Stat4 ^^^^^^ value to be 0x0800. Don't change it */
|
||||
#define SQLITE_PushDown 0x1000 /* The push-down optimization */
|
||||
#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
|
||||
#define SQLITE_SkipScan 0x4000 /* Skip-scans */
|
||||
#define SQLITE_PropagateConst 0x8000 /* The constant propagation opt */
|
||||
#define SQLITE_AllOpts 0xffff /* All optimizations */
|
||||
#define SQLITE_QueryFlattener 0x00000001 /* Query flattening */
|
||||
#define SQLITE_WindowFunc 0x00000002 /* Use xInverse for window functions */
|
||||
#define SQLITE_GroupByOrder 0x00000004 /* GROUPBY cover of ORDERBY */
|
||||
#define SQLITE_FactorOutConst 0x00000008 /* Constant factoring */
|
||||
#define SQLITE_DistinctOpt 0x00000010 /* DISTINCT using indexes */
|
||||
#define SQLITE_CoverIdxScan 0x00000020 /* Covering index scans */
|
||||
#define SQLITE_OrderByIdxJoin 0x00000040 /* ORDER BY of joins via index */
|
||||
#define SQLITE_Transitive 0x00000080 /* Transitive constraints */
|
||||
#define SQLITE_OmitNoopJoin 0x00000100 /* Omit unused tables in joins */
|
||||
#define SQLITE_CountOfView 0x00000200 /* The count-of-view optimization */
|
||||
#define SQLITE_CursorHints 0x00000400 /* Add OP_CursorHint opcodes */
|
||||
#define SQLITE_Stat4 0x00000800 /* Use STAT4 data */
|
||||
/* TH3 expects this value ^^^^^^^^^^ to be 0x0000800. Don't change it */
|
||||
#define SQLITE_PushDown 0x00001000 /* The push-down optimization */
|
||||
#define SQLITE_SimplifyJoin 0x00002000 /* Convert LEFT JOIN to JOIN */
|
||||
#define SQLITE_SkipScan 0x00004000 /* Skip-scans */
|
||||
#define SQLITE_PropagateConst 0x00008000 /* The constant propagation opt */
|
||||
#define SQLITE_MinMaxOpt 0x00010000 /* The min/max optimization */
|
||||
#define SQLITE_AllOpts 0xffffffff /* All optimizations */
|
||||
|
||||
/*
|
||||
** Macros for testing whether or not optimizations are enabled or disabled.
|
||||
@ -4341,6 +4342,7 @@ LogEst sqlite3WhereOutputRowCount(WhereInfo*);
|
||||
int sqlite3WhereIsDistinct(WhereInfo*);
|
||||
int sqlite3WhereIsOrdered(WhereInfo*);
|
||||
int sqlite3WhereOrderByLimitOptLabel(WhereInfo*);
|
||||
void sqlite3WhereMinMaxOptEarlyOut(Vdbe*,WhereInfo*);
|
||||
int sqlite3WhereIsSorted(WhereInfo*);
|
||||
int sqlite3WhereContinueLabel(WhereInfo*);
|
||||
int sqlite3WhereBreakLabel(WhereInfo*);
|
||||
|
26
src/where.c
26
src/where.c
@ -99,6 +99,32 @@ int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){
|
||||
return pInner->addrNxt;
|
||||
}
|
||||
|
||||
/*
|
||||
** While generating code for the min/max optimization, after handling
|
||||
** the aggregate-step call to min() or max(), check to see if any
|
||||
** additional looping is required. If the output order is such that
|
||||
** we are certain that the correct answer has already been found, then
|
||||
** code an OP_Goto to by pass subsequent processing.
|
||||
**
|
||||
** Any extra OP_Goto that is coded here is an optimization. The
|
||||
** correct answer should be obtained regardless. This OP_Goto just
|
||||
** makes the answer appear faster.
|
||||
*/
|
||||
void sqlite3WhereMinMaxOptEarlyOut(Vdbe *v, WhereInfo *pWInfo){
|
||||
WhereLevel *pInner;
|
||||
int i;
|
||||
if( !pWInfo->bOrderedInnerLoop ) return;
|
||||
if( pWInfo->nOBSat==0 ) return;
|
||||
for(i=pWInfo->nLevel-1; i>=0; i--){
|
||||
pInner = &pWInfo->a[i];
|
||||
if( (pInner->pWLoop->wsFlags & WHERE_COLUMN_IN)!=0 ){
|
||||
sqlite3VdbeGoto(v, pInner->addrNxt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
sqlite3VdbeGoto(v, pWInfo->iBreak);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the VDBE address or label to jump to in order to continue
|
||||
** immediately with the next row of a WHERE clause.
|
||||
|
Loading…
x
Reference in New Issue
Block a user