aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2021-01-13 15:23:17 +0000
committerdrh <>2021-01-13 15:23:17 +0000
commitd193057ad147fe038d0f85c68cd914fa9d91c40c (patch)
treead74415cb2afab0b6056dfa9c7edea0f684d579e /src
parentaa556b0fa7ae3f96df773f20d86c51186be25f52 (diff)
downloadsqlite-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.c8
-rw-r--r--src/sqliteInt.h1
-rw-r--r--src/where.c23
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.
*/