aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <Dan Kennedy>2022-12-03 18:16:25 +0000
committerdan <Dan Kennedy>2022-12-03 18:16:25 +0000
commitf6f01f15dd9ff495ac59f5abc3bbe15f4d8e88c8 (patch)
treea86050a52d627e409f41dc8e0dd75623a9830b67 /src
parent231ff4b027b077ce9ac0c829cd9cee4108ca9b7a (diff)
downloadsqlite-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.c5
-rw-r--r--src/select.c27
-rw-r--r--src/vdbe.h4
-rw-r--r--src/vdbeInt.h10
-rw-r--r--src/vdbeapi.c12
-rw-r--r--src/vdbeaux.c16
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