Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add the OP_SorterColumns opcode - an experiment in using a special case opcode to decode the Sorter output rather than the generic OP_Column. This might be faster. And with further work, it could eventually eliminate the need for OP_OpenPseudo. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | OP_SorterColumns |
Files: | files | file ages | folders |
SHA1: |
b9c695e8859bb9972a9890bf2ccf341c |
User & Date: | drh 2014-10-13 01:23:51.730 |
Context
2014-10-13
| ||
12:30 | Use OP_SorterColumns in aggregate queries. Remove OPFLAG_CLEARCACHE. (Closed-Leaf check-in: 134e65c07f user: drh tags: OP_SorterColumns) | |
01:23 | Add the OP_SorterColumns opcode - an experiment in using a special case opcode to decode the Sorter output rather than the generic OP_Column. This might be faster. And with further work, it could eventually eliminate the need for OP_OpenPseudo. (check-in: b9c695e885 user: drh tags: OP_SorterColumns) | |
2014-10-12
| ||
22:37 | Remove the VdbeCursor.lastRowid cache of the current rowid, since maintaining the correct cache value uses more CPU cycles than just recomputing the rowid on the occasions when it is actually needed. Replace it with the VdbeCursor.aOffset field which used to be computed from VdbeCursor.aType when needed. Saves 100 bytes of code space and runs 0.2% faster. (check-in: 91384a7d72 user: drh tags: trunk) | |
Changes
Changes to src/select.c.
︙ | ︙ | |||
1167 1168 1169 1170 1171 1172 1173 | int nColumn, /* Number of columns of data */ SelectDest *pDest /* Write the sorted results here */ ){ Vdbe *v = pParse->pVdbe; /* The prepared statement */ int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */ int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ int addr; | < < < < | 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 | int nColumn, /* Number of columns of data */ SelectDest *pDest /* Write the sorted results here */ ){ Vdbe *v = pParse->pVdbe; /* The prepared statement */ int addrBreak = sqlite3VdbeMakeLabel(v); /* Jump here to exit loop */ int addrContinue = sqlite3VdbeMakeLabel(v); /* Jump here for next cycle */ int addr; int iTab; ExprList *pOrderBy = pSort->pOrderBy; int eDest = pDest->eDest; int iParm = pDest->iSDParm; int regRow; int regRowid; int nKey; int nSortData; /* Trailing values to read from sorter */ int i; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS struct ExprList_item *aOutEx = p->pEList->a; #endif if( pSort->labelBkOut ){ sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut); sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak); |
︙ | ︙ | |||
1202 1203 1204 1205 1206 1207 1208 | regRowid = sqlite3GetTempReg(pParse); regRow = sqlite3GetTempReg(pParse); nSortData = 1; } nKey = pOrderBy->nExpr - pSort->nOBSat; if( pSort->sortFlags & SORTFLAG_UseSorter ){ int regSortOut = ++pParse->nMem; | < < < < < < | < < < < < | | < | > | 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 | regRowid = sqlite3GetTempReg(pParse); regRow = sqlite3GetTempReg(pParse); nSortData = 1; } nKey = pOrderBy->nExpr - pSort->nOBSat; if( pSort->sortFlags & SORTFLAG_UseSorter ){ int regSortOut = ++pParse->nMem; addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut); sqlite3VdbeAddOp4Int(v, OP_SorterColumns, nKey, nSortData, regRow, regSortOut); }else{ addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v); codeOffset(v, p->iOffset, addrContinue); for(i=0; i<nSortData; i++){ sqlite3VdbeAddOp3(v, OP_Column, iTab, nKey+i+1, regRow+i); VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan)); } } switch( eDest ){ case SRT_Table: case SRT_EphemTab: { testcase( eDest==SRT_Table ); testcase( eDest==SRT_EphemTab ); sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 | pCrsr = pC->pCursor; assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */ assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */ /* If the cursor cache is stale, bring it up-to-date */ rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; if( pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){ if( pC->nullRow ){ if( pCrsr==0 ){ assert( pC->pseudoTableReg>0 ); pReg = &aMem[pC->pseudoTableReg]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); | > | 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 | pCrsr = pC->pCursor; assert( pCrsr!=0 || pC->pseudoTableReg>0 ); /* pCrsr NULL on PseudoTables */ assert( pCrsr!=0 || pC->nullRow ); /* pC->nullRow on PseudoTables */ /* If the cursor cache is stale, bring it up-to-date */ rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; assert( (pOp->p5&OPFLAG_CLEARCACHE)==0 || aOp[pc-1].opcode==OP_SorterData ); if( pC->cacheStatus!=p->cacheCtr || (pOp->p5&OPFLAG_CLEARCACHE)!=0 ){ if( pC->nullRow ){ if( pCrsr==0 ){ assert( pC->pseudoTableReg>0 ); pReg = &aMem[pC->pseudoTableReg]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); |
︙ | ︙ | |||
4247 4248 4249 4250 4251 4252 4253 | /* Opcode: SorterData P1 P2 * * * ** Synopsis: r[P2]=data ** ** Write into register P2 the current sorter data for sorter cursor P1. */ case OP_SorterData: { | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 | /* Opcode: SorterData P1 P2 * * * ** Synopsis: r[P2]=data ** ** Write into register P2 the current sorter data for sorter cursor P1. */ case OP_SorterData: { VdbeCursor *pC; /* Sorting cursor defined by P1 */ pOut = &aMem[pOp->p2]; pC = p->apCsr[pOp->p1]; assert( isSorter(pC) ); rc = sqlite3VdbeSorterRowkey(pC, pOut); assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) ); break; } /* Opcode: SorterColumns P1 P2 P3 P4 * ** Synopsis: r[P3@P2]=decode(r[P4]) ** ** The P4 register contains a record that has just come out of a sorter. ** Decode columns P1 through P1+P2-1 into registers P3..P3+P2-1. ** ** This opcode is much faster than multiple calls to Column since it ** does not need to deal with corrupt record detection or default values ** or any of the other complications associated with a record read ** from disk. */ case OP_SorterColumns: { Mem *pDest; /* Register P3 output register */ Mem *pLast; /* Register P3+P2-1 */ u32 serial_type; /* Serial type of a column value */ u32 idx; /* Index into the record header */ u32 d; /* Index into the data of the record */ int nSkip; /* Number of initial columns to skip */ const u8 *aKey; /* Complete text of the record */ assert( pOp->p4type==P4_INT32 ); assert( pOp->p4.i>0 && pOp->p4.i<=(p->nMem - p->nCursor) ); assert( pOp->p3>pOp->p4.i || pOp->p3+pOp->p2<=pOp->p4.i ); assert( pOp->p1>=0 ); assert( pOp->p2>0 ); assert( aMem[pOp->p4.i].flags & MEM_Blob ); aKey = (const u8*)aMem[pOp->p4.i].z; pDest = &aMem[pOp->p3]; pLast = &pDest[pOp->p2-1]; idx = getVarint32(aKey, d); nSkip = pOp->p1; while( nSkip-- ){ assert( d<=aMem[pOp->p4.i].n ); idx += getVarint32(&aKey[idx], serial_type); d += sqlite3VdbeSerialTypeLen(serial_type); } do{ assert( d<=aMem[pOp->p4.i].n ); idx += getVarint32(&aKey[idx], serial_type); if( VdbeMemDynamic(pDest) ) sqlite3VdbeMemSetNull(pDest); d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pDest); pDest->enc = encoding; REGISTER_TRACE((int)(pDest-aMem), pDest); pDest++; }while( pDest<=pLast ); break; } /* Opcode: RowData P1 P2 * * * ** Synopsis: r[P2]=data ** ** Write into register P2 the complete row data for cursor P1. ** There is no interpretation of the data. ** It is just copied onto the P2 register exactly as |
︙ | ︙ |