]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the OP_SorterColumns opcode - an experiment in using a special case
authordrh <drh@noemail.net>
Mon, 13 Oct 2014 01:23:51 +0000 (01:23 +0000)
committerdrh <drh@noemail.net>
Mon, 13 Oct 2014 01:23:51 +0000 (01:23 +0000)
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.

FossilOrigin-Name: b9c695e8859bb9972a9890bf2ccf341c1282ab77

manifest
manifest.uuid
src/select.c
src/vdbe.c

index 0d0dc6d2490408956a1c972231b69f0b8598faba..c1d4cf991ddb8c50b6ae95ca96ed7083a363f1d2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Remove\sthe\sVdbeCursor.lastRowid\scache\sof\sthe\scurrent\srowid,\ssince\smaintaining\nthe\scorrect\scache\svalue\suses\smore\sCPU\scycles\sthan\sjust\srecomputing\sthe\srowid\non\sthe\soccasions\swhen\sit\sis\sactually\sneeded.\s\sReplace\sit\swith\sthe\nVdbeCursor.aOffset\sfield\swhich\sused\sto\sbe\scomputed\sfrom\sVdbeCursor.aType\nwhen\sneeded.\sSaves\s100\sbytes\sof\scode\sspace\sand\sruns\s0.2%\sfaster.
-D 2014-10-12T22:37:22.384
+C Add\sthe\sOP_SorterColumns\sopcode\s-\san\sexperiment\sin\susing\sa\sspecial\scase\nopcode\sto\sdecode\sthe\sSorter\soutput\srather\sthan\sthe\sgeneric\sOP_Column.\s\sThis\nmight\sbe\sfaster.\s\sAnd\swith\sfurther\swork,\sit\scould\seventually\seliminate\sthe\nneed\sfor\sOP_OpenPseudo.
+D 2014-10-13T01:23:51.730
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -227,7 +227,7 @@ F src/printf.c 6b79bbd063dcbadca4cf617a4cde255bcc13ea64
 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
 F src/resolve.c a3466128b52a86c466e47ac1a19e2174f7b5cf89
 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
-F src/select.c f11533162b57ed5ed37f549add34cbcdf51f6712
+F src/select.c d32a3d223c4c0981998d69570fe095d0e563b7f6
 F src/shell.c 18ee8bbe9502d8848072dc2eddd1ea09254ba494
 F src/sqlite.h.in 4a5e5158c189d2bcd45c7c4607c2c0eb6d25c153
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
@@ -289,7 +289,7 @@ F src/update.c 729f6f18fc27740591d085e1172cebe311144bf0
 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
 F src/util.c 4006c01772bd8d8ac4306d523bbcee41d3e392d8
 F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a
-F src/vdbe.c 97c6c50e272ed531bc3af308d5f156cfca0ce4f4
+F src/vdbe.c 5ffd7b182590606bb7db22628caf76cf3fad918e
 F src/vdbe.h 09f5b4e3719fa454f252322b1cdab5cf1f361327
 F src/vdbeInt.h e1173bd72b282633c2ec8f3a2f78b5117229f268
 F src/vdbeapi.c 37a6c6ae284a97bcace365f2f0a225680c0499d9
@@ -1204,7 +1204,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 869c30e45cc87063be423c650f16b99e8adb3df0
-R d569318d3e6a6b025c49ffecae9bf7d4
+P 91384a7d727ef0f285cd430e829ba9f3852db50e
+R 34c56059a01c319cb8bc18ad3acf3cfb
+T *branch * OP_SorterColumns
+T *sym-OP_SorterColumns *
+T -sym-trunk *
 U drh
-Z e6cf351e034f82bffef92232dfc65ffe
+Z 13a10a4b7865e9465444cc45982ddc50
index a04b930976d047684a92412a34c472e3c9eede1c..d2c4891157b72aa882ec231685246f9e2c264c01 100644 (file)
@@ -1 +1 @@
-91384a7d727ef0f285cd430e829ba9f3852db50e
\ No newline at end of file
+b9c695e8859bb9972a9890bf2ccf341c1282ab77
\ No newline at end of file
index 411bca0df44ae359d15f1b5c0382db145257ff50..8d03c856be018493596ca9725678da7eb592a7b9 100644 (file)
@@ -1171,7 +1171,6 @@ static void generateSortTail(
   int addrBreak = sqlite3VdbeMakeLabel(v);     /* Jump here to exit loop */
   int addrContinue = sqlite3VdbeMakeLabel(v);  /* Jump here for next cycle */
   int addr;
-  int addrOnce = 0;
   int iTab;
   ExprList *pOrderBy = pSort->pOrderBy;
   int eDest = pDest->eDest;
@@ -1179,11 +1178,8 @@ static void generateSortTail(
   int regRow;
   int regRowid;
   int nKey;
-  int iSortTab;                   /* Sorter cursor to read from */
   int nSortData;                  /* Trailing values to read from sorter */
-  u8 p5;                          /* p5 parameter for 1st OP_Column */
   int i;
-  int bSeq;                       /* True if sorter record includes seq. no. */
 #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   struct ExprList_item *aOutEx = p->pEList->a;
 #endif
@@ -1206,29 +1202,18 @@ static void generateSortTail(
   nKey = pOrderBy->nExpr - pSort->nOBSat;
   if( pSort->sortFlags & SORTFLAG_UseSorter ){
     int regSortOut = ++pParse->nMem;
-    iSortTab = pParse->nTab++;
-    if( pSort->labelBkOut ){
-      addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
-    }
-    sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData);
-    if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
     addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
     VdbeCoverage(v);
     codeOffset(v, p->iOffset, addrContinue);
     sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
-    p5 = OPFLAG_CLEARCACHE;
-    bSeq = 0;
+    sqlite3VdbeAddOp4Int(v, OP_SorterColumns, nKey, nSortData, regRow, regSortOut);
   }else{
     addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
     codeOffset(v, p->iOffset, addrContinue);
-    iSortTab = iTab;
-    p5 = 0;
-    bSeq = 1;
-  }
-  for(i=0; i<nSortData; i++){
-    sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
-    if( i==0 ) sqlite3VdbeChangeP5(v, p5);
-    VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
+    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:
index 347b604bf4463315aa696e80ffe4419cc392d3e5..4afde4c6c4875cd23bc869c57843dbdca22faf42 100644 (file)
@@ -2288,6 +2288,7 @@ case OP_Column: {
   /* 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 ){
@@ -4251,7 +4252,7 @@ case OP_SorterCompare: {
 ** Write into register P2 the current sorter data for sorter cursor P1.
 */
 case OP_SorterData: {
-  VdbeCursor *pC;
+  VdbeCursor *pC;         /* Sorting cursor defined by P1 */
 
   pOut = &aMem[pOp->p2];
   pC = p->apCsr[pOp->p1];
@@ -4261,6 +4262,54 @@ case OP_SorterData: {
   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
 **