mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Add CYCLES scanstat measurement to "USE TEMP B-TREE FOR ORDER BY" lines.
FossilOrigin-Name: 365011ae8b7e3fcaa2c4ea9601231a3ef2223e60d7a53ec33013109dca22ad58
This commit is contained in:
27
manifest
27
manifest
@ -1,5 +1,5 @@
|
||||
C Enhance\sthe\ssqlite3_stmt_scanstatus()\sAPI\sand\sadd\ssqlite3_stmt_scanstatus_v2().\sFor\screation\sof\seasier\sto\sread\squery\sperformance\sreports.
|
||||
D 2022-12-02T20:32:22.142
|
||||
C Add\sCYCLES\sscanstat\smeasurement\sto\s"USE\sTEMP\sB-TREE\sFOR\sORDER\sBY"\slines.
|
||||
D 2022-12-03T18:16:25.876
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -595,7 +595,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5
|
||||
F src/dbpage.c f1a87f4ebcf22284e0aaf0697862f4ccfc120dcd6db3d8dfa3b049b2580c01d8
|
||||
F src/dbstat.c a56a7ad1163a9888d46cd5820be2e65354fb1aa04ed6909f7c3e5831e0ee2c29
|
||||
F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e
|
||||
F src/expr.c 7b44a97e14ebb679c14ced7c3db420fd6293c33f8bd668fef37746e76afdc746
|
||||
F src/expr.c 02a24db96257d0d0dfc82401a6720ae3156cd20b60b84db9523aaf87884a3254
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002
|
||||
F src/func.c 7e86074afc4dc702691a29b7801f6dcc191db092b52e8bbe69dcd2f7be52194d
|
||||
@ -645,7 +645,7 @@ F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764
|
||||
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
|
||||
F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c b1301741aed7014beafb4cbc524d725865a890c7619d784e4ffb04379259ae6c
|
||||
F src/select.c f6674cdcb839f118cf931b0c49e94d5fd37007a616239f62882d02df51cacbe7
|
||||
F src/shell.c.in 0e45a91da5426563c5b0c8f66fd51d5a5fcb3cc17faa44cd4ea8cc386bde146b
|
||||
F src/sqlite.h.in 3ba99a3c2b414b9ad36d06e2f273ab6077f5f74e4d79630aee047394b92f7c7f
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
@ -718,10 +718,10 @@ F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
|
||||
F src/util.c 313f3154e2b85a447326f5dd15de8d31a4df6ab0c3579bd58f426ff634ec9050
|
||||
F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd
|
||||
F src/vdbe.c 5f5cc749c999d65e2115bb3ec555f7ac0ecfbda7f47526272d53a032e9d083b1
|
||||
F src/vdbe.h 247b4ffaad9ba2b2944a2b3084936ae5df684a42151552f32f074ec847c1402b
|
||||
F src/vdbeInt.h 9628718a289cf3bf490db1435019773ccc0874e1a505502ea477c5a98e649128
|
||||
F src/vdbeapi.c 592c3d7be7c23d202cf5bfb96fc970ced7aaaa1b51052868f1deb91bbbb0add8
|
||||
F src/vdbeaux.c 600edaa2d20eb28aea9707148f4edcf12b349418fd2e3f1de92e5d23fdfc0eb8
|
||||
F src/vdbe.h 77b3fb0abe5c5edaca849816584f0fd019c0f91e80410ef2d65f57fcf290ddd8
|
||||
F src/vdbeInt.h e83be1eea422758d42302941e96e59d93193c373da655a87befdc03a851e0f95
|
||||
F src/vdbeapi.c fed69b846866f1c74a17b8217497f379d1815256220006c072867737c43a741c
|
||||
F src/vdbeaux.c 7dcaff5933e4fbe5983be435b7cd2951d5f3ebd0f2acaf70fed4271dbfb57981
|
||||
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
|
||||
F src/vdbemem.c 6cfed43758d57b6e3b99d9cdedfeccd86e45a07e427b22d8487cbdbebb6c522a
|
||||
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
|
||||
@ -1457,7 +1457,7 @@ F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
|
||||
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
|
||||
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
|
||||
F test/scanstatus.test 7dbcfd6adc6a8df6abc59f83d6da5a27e1bce0b2f6fa55147c8176d7c44e0450
|
||||
F test/scanstatus2.test c618c5843257e290647dd63672c16b0f6488faebc64ba9b2ec5b4de3bb39a7cc
|
||||
F test/scanstatus2.test 7c4fb011e8018b638a39acfa8a93599b991ad0e56872df4556abf375d9663e95
|
||||
F test/schema.test 5dd11c96ba64744de955315d2e4f8992e447533690153b93377dffb2a5ef5431
|
||||
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
||||
F test/schema3.test 8ed4ae66e082cdd8b1b1f22d8549e1e7a0db4527a8e6ee8b6193053ee1e5c9ce
|
||||
@ -2066,11 +2066,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 57dd593ef0efa17dfb3a9f4eac36d5b8b879e271de817d8cd94a8c8b56d31870
|
||||
R 49b81422f59a6a7338c393b5956057f1
|
||||
T *branch * scanstatus_v2
|
||||
T *sym-scanstatus_v2 *
|
||||
T -sym-trunk *
|
||||
P 55800833645739efeddcacef464c623931cb6aeb43f4219b4e4faf473c25c8bb
|
||||
R 3092b93947ce4f84b005f0cef9aa6957
|
||||
U dan
|
||||
Z e87234282222fcab550cd1e86b10e65b
|
||||
Z 8d82637b2296891fd9a0f7cdb6b7a23f
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
55800833645739efeddcacef464c623931cb6aeb43f4219b4e4faf473c25c8bb
|
||||
365011ae8b7e3fcaa2c4ea9601231a3ef2223e60d7a53ec33013109dca22ad58
|
@ -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) );
|
||||
|
27
src/select.c
27
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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -94,6 +94,12 @@ proc do_graph_test {tn sql res} {
|
||||
uplevel [list do_test $tn [list set {} $graph] [string trim $res]]
|
||||
}
|
||||
|
||||
proc puts_graph {sql} {
|
||||
db eval $sql
|
||||
set stmt [db version -last-stmt-ptr]
|
||||
puts [string trim [get_graph $stmt]]
|
||||
}
|
||||
|
||||
|
||||
do_zexplain_test 0 1.1 {
|
||||
SELECT (SELECT a FROM t1 WHERE b=x) FROM t2 WHERE y=2
|
||||
|
Reference in New Issue
Block a user