diff options
author | dan <Dan Kennedy> | 2022-12-03 18:16:25 +0000 |
---|---|---|
committer | dan <Dan Kennedy> | 2022-12-03 18:16:25 +0000 |
commit | f6f01f15dd9ff495ac59f5abc3bbe15f4d8e88c8 (patch) | |
tree | a86050a52d627e409f41dc8e0dd75623a9830b67 /src | |
parent | 231ff4b027b077ce9ac0c829cd9cee4108ca9b7a (diff) | |
download | sqlite-f6f01f15dd9ff495ac59f5abc3bbe15f4d8e88c8.tar.gz sqlite-f6f01f15dd9ff495ac59f5abc3bbe15f4d8e88c8.zip |
Add CYCLES scanstat measurement to "USE TEMP B-TREE FOR ORDER BY" lines.
FossilOrigin-Name: 365011ae8b7e3fcaa2c4ea9601231a3ef2223e60d7a53ec33013109dca22ad58
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 5 | ||||
-rw-r--r-- | src/select.c | 27 | ||||
-rw-r--r-- | src/vdbe.h | 4 | ||||
-rw-r--r-- | src/vdbeInt.h | 10 | ||||
-rw-r--r-- | src/vdbeapi.c | 12 | ||||
-rw-r--r-- | src/vdbeaux.c | 16 |
6 files changed, 60 insertions, 14 deletions
diff --git a/src/expr.c b/src/expr.c index 07e44a187..1528877e2 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3258,7 +3258,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ int nReg; /* Registers to allocate */ Expr *pLimit; /* New limit expression */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS - int addrExplain; + int addrExplain; /* Address of OP_Explain instruction */ #endif Vdbe *v = pParse->pVdbe; @@ -3356,8 +3356,7 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ if( addrOnce ){ sqlite3VdbeJumpHere(v, addrOnce); } - sqlite3VdbeScanStatusEnd(v, addrExplain); - + sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); /* Subroutine return */ assert( ExprUseYSub(pExpr) ); diff --git a/src/select.c b/src/select.c index 740372525..7d010c624 100644 --- a/src/select.c +++ b/src/select.c @@ -65,6 +65,10 @@ struct SortCtx { } aDefer[4]; #endif struct RowLoadInfo *pDeferredRowLoad; /* Deferred row loading info or NULL */ +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + int addrPushStart; /* First instruction to push data into sorter */ + int addrPushEnd; /* Last instruction that pushes data into sorter */ +#endif }; #define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */ @@ -721,6 +725,10 @@ static void pushOntoSorter( */ assert( nData==1 || regData==regOrigData || regOrigData==0 ); +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + pSort->addrPushStart = sqlite3VdbeCurrentAddr(v); +#endif + if( nPrefixReg ){ assert( nPrefixReg==nExpr+bSeq ); regBase = regData - nPrefixReg; @@ -821,6 +829,9 @@ static void pushOntoSorter( sqlite3VdbeChangeP2(v, iSkip, pSort->labelOBLopt ? pSort->labelOBLopt : sqlite3VdbeCurrentAddr(v)); } +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + pSort->addrPushEnd = sqlite3VdbeCurrentAddr(v)-1; +#endif } /* @@ -1647,6 +1658,16 @@ static void generateSortTail( int bSeq; /* True if sorter record includes seq. no. */ int nRefKey = 0; struct ExprList_item *aOutEx = p->pEList->a; +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS + int addrExplain; /* Address of OP_Explain instruction */ +#endif + + ExplainQueryPlan2(addrExplain, (pParse, 0, + "USE TEMP B-TREE FOR %sORDER BY", pSort->nOBSat>0?"RIGHT PART OF ":"") + ); + sqlite3VdbeScanStatusRange( + v, addrExplain, pSort->addrPushStart, pSort->addrPushEnd + ); assert( addrBreak<0 ); if( pSort->labelBkOut ){ @@ -1759,6 +1780,7 @@ static void generateSortTail( VdbeComment((v, "%s", aOutEx[i].zEName)); } } + sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); switch( eDest ){ case SRT_Table: case SRT_EphemTab: { @@ -1820,6 +1842,7 @@ static void generateSortTail( }else{ sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v); } + sqlite3VdbeScanStatusRange(v, addrExplain, sqlite3VdbeCurrentAddr(v)-1, -1); if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn); sqlite3VdbeResolveLabel(v, addrBreak); } @@ -7305,7 +7328,7 @@ int sqlite3Select( if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1); VdbeComment((v, "end %!S", pItem)); - sqlite3VdbeScanStatusEnd(v, addrExplain); + sqlite3VdbeScanStatusRange(v, addrExplain, addrExplain, -1); sqlite3VdbeJumpHere(v, topAddr); sqlite3ClearTempRegCache(pParse); if( pItem->fg.isCte && pItem->fg.isCorrelated==0 ){ @@ -8060,8 +8083,6 @@ int sqlite3Select( ** and send them to the callback one by one. */ if( sSort.pOrderBy ){ - explainTempTable(pParse, - sSort.nOBSat>0 ? "RIGHT PART OF ORDER BY":"ORDER BY"); assert( p->pEList==pEList ); generateSortTail(pParse, p, &sSort, pEList->nExpr, pDest); } diff --git a/src/vdbe.h b/src/vdbe.h index 16690f085..8d0c8123f 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -387,10 +387,10 @@ int sqlite3VdbeBytecodeVtabInit(sqlite3*); #ifdef SQLITE_ENABLE_STMT_SCANSTATUS void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*); -void sqlite3VdbeScanStatusEnd(Vdbe*, int); +void sqlite3VdbeScanStatusRange(Vdbe*, int, int, int); #else # define sqlite3VdbeScanStatus(a,b,c,d,e,f) -# define sqlite3VdbeScanStatusEnd(a,b) +# define sqlite3VdbeScanStatusRange(a,b,c,d) #endif #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) diff --git a/src/vdbeInt.h b/src/vdbeInt.h index b8642da50..df47e0544 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -388,11 +388,19 @@ typedef unsigned bft; /* Bit Field Type */ /* The ScanStatus object holds a single value for the ** sqlite3_stmt_scanstatus() interface. +** +** aAddrRange[]: +** This array is used by ScanStatus elements associated with EQP +** notes that make an SQLITE_SCANSTAT_NCYCLE value available. It is +** an array of up to 3 ranges of VM addresses for which the Vdbe.anCycle[] +** values should be summed to calculate the NCYCLE value. Each pair of +** integer addresses is a start and end address (both inclusive) for a range +** instructions. A start value of 0 indicates an empty range. */ typedef struct ScanStatus ScanStatus; struct ScanStatus { int addrExplain; /* OP_Explain for loop */ - int addrEndRange; /* End of range (inclusive) of times to sum */ + int aAddrRange[6]; int addrLoop; /* Address of "loops" counter */ int addrVisit; /* Address of "rows visited" counter */ int iSelectID; /* The "Select-ID" for this loop */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 90b0cc60c..c00980d6b 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -2207,11 +2207,17 @@ int sqlite3_stmt_scanstatus_v2( } case SQLITE_SCANSTAT_NCYCLE: { i64 res = -1; - if( pScan->addrEndRange ){ + if( pScan->aAddrRange[0] ){ int ii; res = 0; - for(ii=pScan->addrExplain; ii<=pScan->addrEndRange; ii++){ - res += p->anCycle[ii]; + for(ii=0; ii<ArraySize(pScan->aAddrRange); ii+=2){ + int iIns = pScan->aAddrRange[ii]; + int iEnd = pScan->aAddrRange[ii+1]; + if( iIns==0 ) break; + while( iIns<=iEnd ){ + res += p->anCycle[iIns]; + iIns++; + } } } *(i64*)pOut = res; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index e7cd61f05..74d3866c4 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1128,7 +1128,12 @@ void sqlite3VdbeScanStatus( } } -void sqlite3VdbeScanStatusEnd(Vdbe *p, int addrExplain){ +void sqlite3VdbeScanStatusRange( + Vdbe *p, + int addrExplain, + int addrStart, + int addrEnd +){ ScanStatus *pScan = 0; int ii; for(ii=p->nScan-1; ii>=0; ii--){ @@ -1137,7 +1142,14 @@ void sqlite3VdbeScanStatusEnd(Vdbe *p, int addrExplain){ pScan = 0; } if( pScan ){ - pScan->addrEndRange = sqlite3VdbeCurrentAddr(p)-1; + if( addrEnd<0 ) addrEnd = sqlite3VdbeCurrentAddr(p)-1; + for(ii=0; ii<ArraySize(pScan->aAddrRange); ii+=2){ + if( pScan->aAddrRange[ii]==0 ){ + pScan->aAddrRange[ii] = addrStart; + pScan->aAddrRange[ii+1] = addrEnd; + break; + } + } } } #endif |