Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Further enhancements to the min/max optimization of check-in b8ba2f17f938c035 to fix the performance regression identified by forum post 4050026ab8. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | minmax-opt-exp |
Files: | files | file ages | folders |
SHA3-256: |
188772a1dbaf066fbddd39c718fdd874 |
User & Date: | drh 2021-01-13 15:23:17 |
Original Comment: | Further enhancements to the min/max optimization of check-in b8ba2f17f938c035 to fix the performance regression identified by forum post 623f571482. |
Context
2021-01-13
| ||
19:28 | Expand the number of optimization-disable bits from 16 to 32. Use one of the new bits to disable the min/max optimization, so that we can more easily verify that we get the same answer both with and within that optimization. (check-in: fd0c9a12 user: drh tags: minmax-opt-exp) | |
15:23 | Further enhancements to the min/max optimization of check-in b8ba2f17f938c035 to fix the performance regression identified by forum post 4050026ab8. (check-in: 188772a1 user: drh tags: minmax-opt-exp) | |
12:59 | cli: Omit surplus whitespace at the end of lines in .explain output. (check-in: 11e4eb09 user: drh tags: trunk) | |
Changes
Changes to src/select.c.
︙ | ︙ | |||
6769 6770 6771 6772 6773 6774 6775 | updateAccumulator(pParse, iUseFlag, pAggInfo); sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); VdbeComment((v, "indicate data in accumulator")); /* End of the loop */ if( groupBySort ){ | | | 6769 6770 6771 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 | updateAccumulator(pParse, iUseFlag, pAggInfo); sqlite3VdbeAddOp2(v, OP_Integer, 1, iUseFlag); VdbeComment((v, "indicate data in accumulator")); /* End of the loop */ if( groupBySort ){ sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop); VdbeCoverage(v); }else{ sqlite3WhereEnd(pWInfo); sqlite3VdbeChangeToNoop(v, addrSortingIdx); } /* Output the final row of result |
︙ | ︙ | |||
6881 6882 6883 6884 6885 6886 6887 | sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO); } sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem); sqlite3VdbeAddOp1(v, OP_Close, iCsr); explainSimpleCount(pParse, pTab, pBest); }else{ int regAcc = 0; /* "populate accumulators" flag */ | < | 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 | sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO); } sqlite3VdbeAddOp2(v, OP_Count, iCsr, pAggInfo->aFunc[0].iMem); sqlite3VdbeAddOp1(v, OP_Close, iCsr); explainSimpleCount(pParse, pTab, pBest); }else{ int regAcc = 0; /* "populate accumulators" flag */ /* If there are accumulator registers but no min() or max() functions ** without FILTER clauses, allocate register regAcc. Register regAcc ** will contain 0 the first time the inner loop runs, and 1 thereafter. ** The code generated by updateAccumulator() uses this to ensure ** that the accumulator registers are (a) updated only once if ** there are no min() or max functions or (b) always updated for the |
︙ | ︙ | |||
6930 6931 6932 6933 6934 6935 6936 | pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, 0, minMaxFlag, 0); if( pWInfo==0 ){ goto select_end; } updateAccumulator(pParse, regAcc, pAggInfo); if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); | | | < | 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 | pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy, 0, minMaxFlag, 0); if( pWInfo==0 ){ goto select_end; } updateAccumulator(pParse, regAcc, pAggInfo); if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc); if( minMaxFlag ){ sqlite3WhereMinMaxOptEarlyOut(v, pWInfo); } sqlite3WhereEnd(pWInfo); finalizeAggFunctions(pParse, pAggInfo); } sSort.pOrderBy = 0; sqlite3ExprIfFalse(pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL); |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 | Upsert*); WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); void sqlite3WhereEnd(WhereInfo*); LogEst sqlite3WhereOutputRowCount(WhereInfo*); int sqlite3WhereIsDistinct(WhereInfo*); int sqlite3WhereIsOrdered(WhereInfo*); int sqlite3WhereOrderByLimitOptLabel(WhereInfo*); int sqlite3WhereIsSorted(WhereInfo*); int sqlite3WhereContinueLabel(WhereInfo*); int sqlite3WhereBreakLabel(WhereInfo*); int sqlite3WhereOkOnePass(WhereInfo*, int*); #define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */ #define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */ #define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ | > | 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 | Upsert*); WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); void sqlite3WhereEnd(WhereInfo*); 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*); int sqlite3WhereOkOnePass(WhereInfo*, int*); #define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */ #define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */ #define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */ |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 | ** continuation of the inner-most loop. */ return pWInfo->iContinue; } pInner = &pWInfo->a[pWInfo->nLevel-1]; assert( pInner->addrNxt!=0 ); return pInner->addrNxt; } /* ** Return the VDBE address or label to jump to in order to continue ** immediately with the next row of a WHERE clause. */ int sqlite3WhereContinueLabel(WhereInfo *pWInfo){ assert( pWInfo->iContinue!=0 ); | > > > > > > > > > > > > > > > > > > > > > > > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | ** continuation of the inner-most loop. */ return pWInfo->iContinue; } pInner = &pWInfo->a[pWInfo->nLevel-1]; assert( pInner->addrNxt!=0 ); 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; 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. */ int sqlite3WhereContinueLabel(WhereInfo *pWInfo){ assert( pWInfo->iContinue!=0 ); |
︙ | ︙ |