diff options
author | drh <> | 2021-01-13 15:23:17 +0000 |
---|---|---|
committer | drh <> | 2021-01-13 15:23:17 +0000 |
commit | d193057ad147fe038d0f85c68cd914fa9d91c40c (patch) | |
tree | ad74415cb2afab0b6056dfa9c7edea0f684d579e /src | |
parent | aa556b0fa7ae3f96df773f20d86c51186be25f52 (diff) | |
download | sqlite-d193057ad147fe038d0f85c68cd914fa9d91c40c.tar.gz sqlite-d193057ad147fe038d0f85c68cd914fa9d91c40c.zip |
Further enhancements to the min/max optimization of
[/info/b8ba2f17f938c035|check-in b8ba2f17f938c035] to fix the performance
regression identified by
[forum:/forumpost/623f571482|forum post 623f571482].
FossilOrigin-Name: 188772a1dbaf066fbddd39c718fdd87478b19a920622f4640bcb79d4ef065331
Diffstat (limited to 'src')
-rw-r--r-- | src/select.c | 8 | ||||
-rw-r--r-- | src/sqliteInt.h | 1 | ||||
-rw-r--r-- | src/where.c | 23 |
3 files changed, 27 insertions, 5 deletions
diff --git a/src/select.c b/src/select.c index f00a3acd8..76806b66e 100644 --- a/src/select.c +++ b/src/select.c @@ -6773,7 +6773,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 +6885,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 +6933,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); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 6d1e598d9..8432fe20c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4341,6 +4341,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*); diff --git a/src/where.c b/src/where.c index 0f219d439..adc688b4b 100644 --- a/src/where.c +++ b/src/where.c @@ -100,6 +100,29 @@ int sqlite3WhereOrderByLimitOptLabel(WhereInfo *pWInfo){ } /* +** 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; + if( !pWInfo->bOrderedInnerLoop ) return; + if( pWInfo->nOBSat==0 ) return; + pInner = &pWInfo->a[pWInfo->nLevel-1]; + if( (pInner->pWLoop->wsFlags & WHERE_COLUMN_IN)==0 ){ + sqlite3VdbeGoto(v, pWInfo->iBreak); + }else if( pInner->addrNxt!=pWInfo->iContinue ){ + sqlite3VdbeGoto(v, pInner->addrNxt); + } +} + +/* ** Return the VDBE address or label to jump to in order to continue ** immediately with the next row of a WHERE clause. */ |