/ Check-in [4cda3b30]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:A proof-of-concept for running sqlite3_blob_open() without using OP_Column when operating on a pure key/value table. This demo does not include any corrupt database checking. Uses about 3% fewer CPU cycles on a key/value performance test.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | kv-access-opt-demo
Files: files | file ages | folders
SHA1: 4cda3b305bd1ca893e40d49d90481f4d403ca50a
User & Date: drh 2017-01-21 15:30:20
Context
2017-01-21
15:30
A proof-of-concept for running sqlite3_blob_open() without using OP_Column when operating on a pure key/value table. This demo does not include any corrupt database checking. Uses about 3% fewer CPU cycles on a key/value performance test. Leaf check-in: 4cda3b30 user: drh tags: kv-access-opt-demo
14:11
Remove an unnecessary sqlite3_bind_int64() call from sqlite3_blob_open(). Also other minor refactoring of the sqlite3_blob implementation. check-in: 9d197a53 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/vdbeblob.c.

68
69
70
71
72
73
74













75


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
...
307
308
309
310
311
312
313






314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
  ** have been down with an extra OP_Goto, but simply setting the program
  ** counter is faster. */
  if( v->pc>3 ) v->pc = 3;

  rc = sqlite3_step(p->pStmt);
  if( rc==SQLITE_ROW ){
    VdbeCursor *pC = v->apCsr[0];













    u32 type = pC->aType[p->iCol];


    if( type<12 ){
      zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
          type==0?"null": type==7?"real": "integer"
      );
      rc = SQLITE_ERROR;
      sqlite3_finalize(p->pStmt);
      p->pStmt = 0;
    }else{
      p->iOffset = pC->aType[p->iCol + pC->nField];
      p->nByte = sqlite3VdbeSerialTypeLen(type);
      p->pCsr =  pC->uc.pCursor;
      sqlite3BtreeIncrblobCursor(p->pCsr);
    }
  }

  if( rc==SQLITE_ROW ){
................................................................................
        ** we can invoke OP_Column to fill in the vdbe cursors type 
        ** and offset cache without causing any IO.
        */
        aOp[1].p4type = P4_INT32;
        aOp[1].p4.i = pTab->nCol+1;
        aOp[3].p2 = pTab->nCol;







        pParse->nVar = 0;
        pParse->nMem = 1;
        pParse->nTab = 1;
        sqlite3VdbeMakeReady(v, pParse);
      }
    }
   
    pBlob->isPureKV = (pTab->nCol==2 && pTab->iPKey==0);
    pBlob->iCol = iCol;
    pBlob->db = db;
    sqlite3BtreeLeaveAll(db);
    if( db->mallocFailed ){
      goto blob_open_out;
    }
    rc = blobSeekToRow(pBlob, iRow, &zErr);







>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>








<







 







>
>
>
>
>
>






|
<







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340

341
342
343
344
345
346
347
  ** have been down with an extra OP_Goto, but simply setting the program
  ** counter is faster. */
  if( v->pc>3 ) v->pc = 3;

  rc = sqlite3_step(p->pStmt);
  if( rc==SQLITE_ROW ){
    VdbeCursor *pC = v->apCsr[0];
    u32 type;
    if( p->isPureKV ){
      u32 avail;
      const u8 *a;
      BtCursor *pCrsr = pC->uc.pCursor;
      sqlite3BtreeEnterCursor(pCrsr);
      (void)sqlite3BtreePayloadSize(pCrsr);
      a = (const u8*)sqlite3BtreePayloadFetch(pCrsr, &avail);
      assert( p->iCol==1 );
      getVarint32(a+2, type);
      sqlite3BtreeLeaveCursor(pCrsr);
      p->iOffset = a[0];
    }else{
      type = pC->aType[p->iCol];
      p->iOffset = pC->aType[p->iCol + pC->nField];
    }
    if( type<12 ){
      zErr = sqlite3MPrintf(p->db, "cannot open value of type %s",
          type==0?"null": type==7?"real": "integer"
      );
      rc = SQLITE_ERROR;
      sqlite3_finalize(p->pStmt);
      p->pStmt = 0;
    }else{

      p->nByte = sqlite3VdbeSerialTypeLen(type);
      p->pCsr =  pC->uc.pCursor;
      sqlite3BtreeIncrblobCursor(p->pCsr);
    }
  }

  if( rc==SQLITE_ROW ){
................................................................................
        ** we can invoke OP_Column to fill in the vdbe cursors type 
        ** and offset cache without causing any IO.
        */
        aOp[1].p4type = P4_INT32;
        aOp[1].p4.i = pTab->nCol+1;
        aOp[3].p2 = pTab->nCol;

   
        if( pTab->nCol==2 && pTab->iPKey==0 && iCol==1 ){
          pBlob->isPureKV = 1;
          aOp[3].opcode = OP_Noop;
        }

        pParse->nVar = 0;
        pParse->nMem = 1;
        pParse->nTab = 1;
        sqlite3VdbeMakeReady(v, pParse);
      }
    }
      

    pBlob->iCol = iCol;
    pBlob->db = db;
    sqlite3BtreeLeaveAll(db);
    if( db->mallocFailed ){
      goto blob_open_out;
    }
    rc = blobSeekToRow(pBlob, iRow, &zErr);