1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Experimental changes to improve the performance of OP_Next.

FossilOrigin-Name: 1a249845251199c00817893add300a1a654b4df9
This commit is contained in:
dan
2011-08-27 18:48:57 +00:00
parent 3d4435b234
commit a205a486d2
6 changed files with 60 additions and 41 deletions

View File

@@ -1,5 +1,5 @@
C Fix\sseveral\sharmless\scompiler\swarnings\sand\sa\sdocumentation\sbug. C Experimental\schanges\sto\simprove\sthe\sperformance\sof\sOP_Next.
D 2011-08-26T20:55:50.529 D 2011-08-27T18:48:57.573
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 8c930e7b493d59099ea1304bd0f2aed152eb3315 F Makefile.in 8c930e7b493d59099ea1304bd0f2aed152eb3315
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -124,7 +124,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 28a4fe55327ff708bfaf9d4326d02686f7a553c3 F src/backup.c 28a4fe55327ff708bfaf9d4326d02686f7a553c3
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c ed13fdefdbe671d5777773dcfb3a162ddb4623ae F src/btree.c bd89d604a532063da8ed1a095f1805db49896325
F src/btree.h 9ddf04226eac592d4cc3709c5a8b33b2351ff5f7 F src/btree.h 9ddf04226eac592d4cc3709c5a8b33b2351ff5f7
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3 F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
F src/build.c 2d5de52df616a3bf5a659cbca85211c46e2ba9bd F src/build.c 2d5de52df616a3bf5a659cbca85211c46e2ba9bd
@@ -238,11 +238,11 @@ F src/update.c 74a6cfb34e9732c1e2a86278b229913b4b51eeec
F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0 F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0
F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7 F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
F src/vdbe.c 4a7191c0f8e918b74e8c84cbdd77746d6b7e3bcf F src/vdbe.c d63854aef07d036987f768dae7ca5c852881ce28
F src/vdbe.h 2bf6ec77d8b9980fc19da6e0b0a36d0dbf884ce4 F src/vdbe.h c1eeedacab6bcf1e7c2cf8203ba9763a616f9a86
F src/vdbeInt.h f9250326f264ca5f100acc19e9c07096bb889096 F src/vdbeInt.h f9250326f264ca5f100acc19e9c07096bb889096
F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98 F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98
F src/vdbeaux.c 11b0df8822ecf61e543562247207df75e2ebb617 F src/vdbeaux.c dd5d10ae523bbc6ed55ac73daa28a9ea1f2fa42a
F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3 F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
F src/vdbesort.c 8a61a6d731cbe612217edf9eece6197f37c9489e F src/vdbesort.c 8a61a6d731cbe612217edf9eece6197f37c9489e
@@ -961,7 +961,10 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2 F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2
P 1dada5158215d1816edb69ff2610f9d2259ce19d P 5454d0fe227b7c1f0e7715b6c08f97019628fc4c
R 16e082a02686bfb3de55c1b850240992 R 06eac31c16dc3f7f5b4649f86c063bf4
U drh T *branch * experimental
Z 9f47e5dd82da8bb114d554ebcb62232c T *sym-experimental *
T -sym-trunk *
U dan
Z 50e65d7380a3dc463f2c091e8241574b

View File

@@ -1 +1 @@
5454d0fe227b7c1f0e7715b6c08f97019628fc4c 1a249845251199c00817893add300a1a654b4df9

View File

@@ -3479,7 +3479,8 @@ static int btreeCursor(
return SQLITE_READONLY; return SQLITE_READONLY;
} }
if( iTable==1 && btreePagecount(pBt)==0 ){ if( iTable==1 && btreePagecount(pBt)==0 ){
return SQLITE_EMPTY; assert( wrFlag==0 );
iTable = 0;
} }
/* Now that no other errors can occur, finish filling in the BtCursor /* Now that no other errors can occur, finish filling in the BtCursor
@@ -4233,6 +4234,9 @@ static int moveToRoot(BtCursor *pCur){
releasePage(pCur->apPage[i]); releasePage(pCur->apPage[i]);
} }
pCur->iPage = 0; pCur->iPage = 0;
}else if( pCur->pgnoRoot==0 ){
pCur->eState = CURSOR_INVALID;
return SQLITE_OK;
}else{ }else{
rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]); rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
@@ -4342,7 +4346,7 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
rc = moveToRoot(pCur); rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
if( pCur->eState==CURSOR_INVALID ){ if( pCur->eState==CURSOR_INVALID ){
assert( pCur->apPage[pCur->iPage]->nCell==0 ); assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
*pRes = 1; *pRes = 1;
}else{ }else{
assert( pCur->apPage[pCur->iPage]->nCell>0 ); assert( pCur->apPage[pCur->iPage]->nCell>0 );
@@ -4381,7 +4385,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
rc = moveToRoot(pCur); rc = moveToRoot(pCur);
if( rc==SQLITE_OK ){ if( rc==SQLITE_OK ){
if( CURSOR_INVALID==pCur->eState ){ if( CURSOR_INVALID==pCur->eState ){
assert( pCur->apPage[pCur->iPage]->nCell==0 ); assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
*pRes = 1; *pRes = 1;
}else{ }else{
assert( pCur->eState==CURSOR_VALID ); assert( pCur->eState==CURSOR_VALID );
@@ -4454,12 +4458,12 @@ int sqlite3BtreeMovetoUnpacked(
if( rc ){ if( rc ){
return rc; return rc;
} }
assert( pCur->apPage[pCur->iPage] ); assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
assert( pCur->apPage[pCur->iPage]->isInit ); assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID ); assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
if( pCur->eState==CURSOR_INVALID ){ if( pCur->eState==CURSOR_INVALID ){
*pRes = -1; *pRes = -1;
assert( pCur->apPage[pCur->iPage]->nCell==0 ); assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
return SQLITE_OK; return SQLITE_OK;
} }
assert( pCur->apPage[0]->intKey || pIdxKey ); assert( pCur->apPage[0]->intKey || pIdxKey );
@@ -7376,6 +7380,11 @@ int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){ int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
i64 nEntry = 0; /* Value to return in *pnEntry */ i64 nEntry = 0; /* Value to return in *pnEntry */
int rc; /* Return code */ int rc; /* Return code */
if( pCur->pgnoRoot==0 ){
*pnEntry = 0;
return SQLITE_OK;
}
rc = moveToRoot(pCur); rc = moveToRoot(pCur);
/* Unless an error occurs, the following loop runs one iteration for each /* Unless an error occurs, the following loop runs one iteration for each

View File

@@ -2550,7 +2550,7 @@ case OP_Count: { /* out2-prerelease */
BtCursor *pCrsr; BtCursor *pCrsr;
pCrsr = p->apCsr[pOp->p1]->pCursor; pCrsr = p->apCsr[pOp->p1]->pCursor;
if( pCrsr ){ if( ALWAYS(pCrsr) ){
rc = sqlite3BtreeCount(pCrsr, &nEntry); rc = sqlite3BtreeCount(pCrsr, &nEntry);
}else{ }else{
nEntry = 0; nEntry = 0;
@@ -3112,15 +3112,9 @@ case OP_OpenWrite: {
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
pCur->pKeyInfo = pKeyInfo; pCur->pKeyInfo = pKeyInfo;
/* Since it performs no memory allocation or IO, the only values that /* Since it performs no memory allocation or IO, the only value that
** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK. ** sqlite3BtreeCursor() may return is SQLITE_OK. */
** SQLITE_EMPTY is only returned when attempting to open the table assert( rc==SQLITE_OK );
** rooted at page 1 of a zero-byte database. */
assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
if( rc==SQLITE_EMPTY ){
pCur->pCursor = 0;
rc = SQLITE_OK;
}
/* Set the VdbeCursor.isTable and isIndex variables. Previous versions of /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
** SQLite used to check if the root-page flags were sane at this point ** SQLite used to check if the root-page flags were sane at this point
@@ -3333,7 +3327,7 @@ case OP_SeekGt: { /* jump, in3 */
assert( OP_SeekGe == OP_SeekLt+2 ); assert( OP_SeekGe == OP_SeekLt+2 );
assert( OP_SeekGt == OP_SeekLt+3 ); assert( OP_SeekGt == OP_SeekLt+3 );
assert( pC->isOrdered ); assert( pC->isOrdered );
if( pC->pCursor!=0 ){ if( ALWAYS(pC->pCursor!=0) ){
oc = pOp->opcode; oc = pOp->opcode;
pC->nullRow = 0; pC->nullRow = 0;
if( pC->isTable ){ if( pC->isTable ){
@@ -3691,7 +3685,7 @@ case OP_NotExists: { /* jump, in3 */
assert( pC->isTable ); assert( pC->isTable );
assert( pC->pseudoTableReg==0 ); assert( pC->pseudoTableReg==0 );
pCrsr = pC->pCursor; pCrsr = pC->pCursor;
if( pCrsr!=0 ){ if( ALWAYS(pCrsr!=0) ){
res = 0; res = 0;
iKey = pIn3->u.i; iKey = pIn3->u.i;
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
@@ -4218,6 +4212,7 @@ case OP_NullRow: {
assert( pC!=0 ); assert( pC!=0 );
pC->nullRow = 1; pC->nullRow = 1;
pC->rowidIsValid = 0; pC->rowidIsValid = 0;
assert( pC->pCursor || pC->pVtabCursor );
if( pC->pCursor ){ if( pC->pCursor ){
sqlite3BtreeClearCursor(pC->pCursor); sqlite3BtreeClearCursor(pC->pCursor);
} }
@@ -4241,7 +4236,7 @@ case OP_Last: { /* jump */
pC = p->apCsr[pOp->p1]; pC = p->apCsr[pOp->p1];
assert( pC!=0 ); assert( pC!=0 );
pCrsr = pC->pCursor; pCrsr = pC->pCursor;
if( pCrsr==0 ){ if( NEVER(pCrsr==0) ){
res = 1; res = 1;
}else{ }else{
rc = sqlite3BtreeLast(pCrsr, &res); rc = sqlite3BtreeLast(pCrsr, &res);
@@ -4296,7 +4291,9 @@ case OP_Rewind: { /* jump */
res = 1; res = 1;
if( isSorter(pC) ){ if( isSorter(pC) ){
rc = sqlite3VdbeSorterRewind(db, pC, &res); rc = sqlite3VdbeSorterRewind(db, pC, &res);
}else if( (pCrsr = pC->pCursor)!=0 ){ }else{
pCrsr = pC->pCursor;
assert( pCrsr );
rc = sqlite3BtreeFirst(pCrsr, &res); rc = sqlite3BtreeFirst(pCrsr, &res);
pC->atFirst = res==0 ?1:0; pC->atFirst = res==0 ?1:0;
pC->deferredMoveto = 0; pC->deferredMoveto = 0;
@@ -4311,7 +4308,7 @@ case OP_Rewind: { /* jump */
break; break;
} }
/* Opcode: Next P1 P2 * * P5 /* Opcode: Next P1 P2 * P4 P5
** **
** Advance cursor P1 so that it points to the next key/data pair in its ** Advance cursor P1 so that it points to the next key/data pair in its
** table or index. If there are no more key/value pairs then fall through ** table or index. If there are no more key/value pairs then fall through
@@ -4320,6 +4317,9 @@ case OP_Rewind: { /* jump */
** **
** The P1 cursor must be for a real table, not a pseudo-table. ** The P1 cursor must be for a real table, not a pseudo-table.
** **
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreeNext().
**
** If P5 is positive and the jump is taken, then event counter ** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented. ** number P5-1 in the prepared statement is incremented.
** **
@@ -4334,13 +4334,15 @@ case OP_Rewind: { /* jump */
** **
** The P1 cursor must be for a real table, not a pseudo-table. ** The P1 cursor must be for a real table, not a pseudo-table.
** **
** P4 is always of type P4_ADVANCE. The function pointer points to
** sqlite3BtreePrevious().
**
** If P5 is positive and the jump is taken, then event counter ** If P5 is positive and the jump is taken, then event counter
** number P5-1 in the prepared statement is incremented. ** number P5-1 in the prepared statement is incremented.
*/ */
case OP_Prev: /* jump */ case OP_Prev: /* jump */
case OP_Next: { /* jump */ case OP_Next: { /* jump */
VdbeCursor *pC; VdbeCursor *pC;
BtCursor *pCrsr;
int res; int res;
CHECK_FOR_INTERRUPT; CHECK_FOR_INTERRUPT;
@@ -4354,15 +4356,12 @@ case OP_Next: { /* jump */
assert( pOp->opcode==OP_Next ); assert( pOp->opcode==OP_Next );
rc = sqlite3VdbeSorterNext(db, pC, &res); rc = sqlite3VdbeSorterNext(db, pC, &res);
}else{ }else{
pCrsr = pC->pCursor;
if( pCrsr==0 ){
pC->nullRow = 1;
break;
}
res = 1; res = 1;
assert( pC->deferredMoveto==0 ); assert( pC->deferredMoveto==0 );
rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) : assert( pC->pCursor );
sqlite3BtreePrevious(pCrsr, &res); assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
rc = pOp->p4.xAdvance(pC->pCursor, &res);
} }
pC->nullRow = (u8)res; pC->nullRow = (u8)res;
pC->cacheStatus = CACHE_STALE; pC->cacheStatus = CACHE_STALE;

View File

@@ -61,6 +61,7 @@ struct VdbeOp {
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
int *ai; /* Used when p4type is P4_INTARRAY */ int *ai; /* Used when p4type is P4_INTARRAY */
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
int (*xAdvance)(BtCursor *, int *);
} p4; } p4;
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
char *zComment; /* Comment to improve readability */ char *zComment; /* Comment to improve readability */
@@ -116,6 +117,7 @@ typedef struct VdbeOpList VdbeOpList;
#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */ #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */ #define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
** is made. That copy is freed when the Vdbe is finalized. But if the ** is made. That copy is freed when the Vdbe is finalized. But if the

View File

@@ -433,6 +433,12 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
n = pOp[-1].p1; n = pOp[-1].p1;
if( n>nMaxArgs ) nMaxArgs = n; if( n>nMaxArgs ) nMaxArgs = n;
#endif #endif
}else if( opcode==OP_Next ){
pOp->p4.xAdvance = sqlite3BtreeNext;
pOp->p4type = P4_ADVANCE;
}else if( opcode==OP_Prev ){
pOp->p4.xAdvance = sqlite3BtreePrevious;
pOp->p4type = P4_ADVANCE;
} }
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){ if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){