]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
This is an untested proof-of-concept for enhancements to RTree that attempt rtree-update-optimization
authordrh <drh@noemail.net>
Fri, 25 May 2018 14:39:24 +0000 (14:39 +0000)
committerdrh <drh@noemail.net>
Fri, 25 May 2018 14:39:24 +0000 (14:39 +0000)
to use sqlite3_value_nochange() to reduce the amount of work associated with
UPDATE operations in cases where either the coordinates or the auxiliary data
is unchanged.

FossilOrigin-Name: 6f7cfeff708521a3ac2f4fb64c37f3f9ae533c661f186ec1763e6bb88907cd4c

ext/rtree/rtree.c
manifest
manifest.uuid

index e1b16ec0f5d04919183e2873c6db86193433f567..fe6b38e8ae68772e28785b9e648efe3745cedd27 100644 (file)
@@ -3076,8 +3076,11 @@ static int rtreeUpdate(
 ){
   Rtree *pRtree = (Rtree *)pVtab;
   int rc = SQLITE_OK;
-  RtreeCell cell;                 /* New cell to insert if nData>1 */
-  int bHaveRowid = 0;             /* Set to 1 after new rowid is determined */
+  RtreeCell cell;              /* New cell to insert if nData>1 */
+  int bHaveRowid = 0;          /* Set to 1 after new rowid is determined */
+  int bRtreeInsert = 0;        /* True if rtree data is to be inserted */
+  int nCoord;                  /* Number of coordinate columns */
+  int ii;                      /* Loop counter */
 
   if( pRtree->nNodeRef ){
     /* Unable to write to the btree while another cursor is reading from it,
@@ -3090,6 +3093,35 @@ static int rtreeUpdate(
 
   cell.iRowid = 0;  /* Used only to suppress a compiler warning */
 
+  /* Set bRtreeInsert if this is an INSERT statement, or if it is an
+  ** UPDATE statement that changes the rowid or one of the coordinates.
+  ** Leave bRtreeInsert at zero if this is a DELETE or if this is an
+  ** UPDATE that only changes auxiliary columns.
+  */
+  if( nData>1 ){
+    nCoord = pRtree->nDim2;
+
+    /* NB: nData can only be less than nDim2+3 if the rtree is mis-declared
+    ** with "column" that are interpreted as table constraints.
+    ** Example:  CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
+    ** This problem was discovered after years of use, so we silently ignore
+    ** these kinds of misdeclared tables to avoid breaking any legacy.
+    */
+    if( nCoord > nData-3 ) nCoord = nData - 3;
+
+    if( sqlite3_value_type(aData[0])==SQLITE_NULL ){
+      bRtreeInsert = 1;   /* This is an INSERT statement */
+    }else{
+      /* This is an UPDATE statement.  Check to see if the rowid (aData[2])
+      ** or any coordinate column (aData[3] through aData[nCoord+2])
+      ** has changed. */
+      for(ii=nCoord+2; ii>=2; ii--){
+        if( !sqlite3_value_nochange(aData[ii]) ) break;
+      }
+      bRtreeInsert = ii>=2;
+    }
+  }
+
   /* Constraint handling. A write operation on an r-tree table may return
   ** SQLITE_CONSTRAINT for two reasons:
   **
@@ -3101,23 +3133,10 @@ static int rtreeUpdate(
   ** case, SQLITE_CONSTRAINT must be returned regardless of the
   ** conflict-handling mode specified by the user.
   */
-  if( nData>1 ){
-    int ii;
-    int nn = nData - 4;
-
-    if( nn > pRtree->nDim2 ) nn = pRtree->nDim2;
-    /* Populate the cell.aCoord[] array. The first coordinate is aData[3].
-    **
-    ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
-    ** with "column" that are interpreted as table constraints.
-    ** Example:  CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
-    ** This problem was discovered after years of use, so we silently ignore
-    ** these kinds of misdeclared tables to avoid breaking any legacy.
-    */
-
+  if( bRtreeInsert ){
 #ifndef SQLITE_RTREE_INT_ONLY
     if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
-      for(ii=0; ii<nn; ii+=2){
+      for(ii=0; ii<nCoord; ii+=2){
         cell.aCoord[ii].f = rtreeValueDown(aData[ii+3]);
         cell.aCoord[ii+1].f = rtreeValueUp(aData[ii+4]);
         if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
@@ -3128,7 +3147,7 @@ static int rtreeUpdate(
     }else
 #endif
     {
-      for(ii=0; ii<nn; ii+=2){
+      for(ii=0; ii<nCoord; ii+=2){
         cell.aCoord[ii].i = sqlite3_value_int(aData[ii+3]);
         cell.aCoord[ii+1].i = sqlite3_value_int(aData[ii+4]);
         if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
@@ -3166,7 +3185,9 @@ static int rtreeUpdate(
   ** record to delete from the r-tree table. The following block does
   ** just that.
   */
-  if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){
+  if( sqlite3_value_type(aData[0])!=SQLITE_NULL
+   && (bRtreeInsert || nData==1)
+  ){
     rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0]));
   }
 
@@ -3174,13 +3195,14 @@ static int rtreeUpdate(
   ** (aData[2]..aData[argc-1]) contain a new record to insert into
   ** the r-tree structure.
   */
-  if( rc==SQLITE_OK && nData>1 ){
+  if( rc==SQLITE_OK && bRtreeInsert ){
     /* Insert the new record into the r-tree */
     RtreeNode *pLeaf = 0;
 
     /* Figure out the rowid of the new row. */
     if( bHaveRowid==0 ){
       rc = newRowid(pRtree, &cell.iRowid);
+      bHaveRowid = 1;
     }
     *pRowid = cell.iRowid;
 
@@ -3196,10 +3218,31 @@ static int rtreeUpdate(
         rc = rc2;
       }
     }
-    if( pRtree->nAux ){
+  }
+
+  /* Handle INSERT and UPDATE of auxiliary column data */
+  if( rc==SQLITE_OK && nData>1 && pRtree->nAux ){
+    if( sqlite3_value_type(aData[0])==SQLITE_NULL ){
+      /* This is an INSERT statement.  Check to see if any
+      ** auxiliary column is non-NULL and hence needs to be set */
+      for(ii=pRtree->nAux+pRtree->nDim2+3; ii<nData; ii++){
+        if( sqlite3_value_type(aData[ii])!=SQLITE_NULL ) break;
+      }
+    }else{
+      /* This is an UPDATE statement.  Check to see if any
+      ** auxiliary column value has changed. */
+      for(ii=pRtree->nAux+pRtree->nDim2+3; ii<nData; ii++){
+        if( sqlite3_value_nochange(aData[ii])==0 ) break;
+      }
+    }
+    if( ii<nData ){
       sqlite3_stmt *pUp = pRtree->pWriteAux;
       int jj;
-      sqlite3_bind_int64(pUp, 1, *pRowid);
+      if( bHaveRowid ){
+        sqlite3_bind_int64(pUp, 1, cell.iRowid);
+      }else{
+        sqlite3_bind_int64(pUp, 1, sqlite3_value_int64(aData[1]));
+      }
       for(jj=0; jj<pRtree->nAux; jj++){
         sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]);
       }
index 721b442bbb03e01bfea1a6acec20f534735fbb1f..13a162a28b6a2878a457fcca8c4680bc86b3d539 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C When\sdoing\sa\sone-pass\sUPDATE\sor\sDELETE\son\svirtual\stables,\sclose\sthe\scursor\nprior\sto\srunning\sVUpdate.\s\sThis\sallows\sone-pass\sto\swork\son\svirtual\stables\nthat\sdo\snot\sallow\sconcurrent\sreads\sand\swrites.\s\sEnhance\srtree\sto\stake\nadvantage\sof\sthis\snew\scapability.
-D 2018-05-24T23:51:57.743
+C This\sis\san\suntested\sproof-of-concept\sfor\senhancements\sto\sRTree\sthat\sattempt\nto\suse\ssqlite3_value_nochange()\sto\sreduce\sthe\samount\sof\swork\sassociated\swith\nUPDATE\soperations\sin\scases\swhere\seither\sthe\scoordinates\sor\sthe\sauxiliary\sdata\nis\sunchanged.
+D 2018-05-25T14:39:24.456
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
@@ -355,7 +355,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
 F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/rtree.c cb6d4bd43c118354fe5b5213843da058259467ecdbac0c6f71ead0fd89acf4ec
+F ext/rtree/rtree.c 1a11f26cbcccc31391fe45e10804b07e64dabc4fb4803fb3d075bfe13360d8b8
 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
 F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
@@ -1729,7 +1729,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 3ba08e53d54165f5541756ad13a4c2f0b18516cb612a256e056ed1ff76c1fa83
-R 52623d992549c096857f92f7f6ff2464
+P b816023ce07d01024d5769e16db924374a49bf909edd12dc1344a0a1ef693db5
+R d13a5739b07f5c3bc2f350a7fd438bb4
+T *branch * rtree-update-optimization
+T *sym-rtree-update-optimization *
+T -sym-trunk *
 U drh
-Z 92fa856c89ee79b753ba76005690f976
+Z 339f042021a37adf237173fa2c6b25c7
index 5d8567b91b1bf43e14be74cd60a7a1be93e43be1..77b8e67cae140bd959b6d0c9b92b9c6d4477e1bc 100644 (file)
@@ -1 +1 @@
-b816023ce07d01024d5769e16db924374a49bf909edd12dc1344a0a1ef693db5
\ No newline at end of file
+6f7cfeff708521a3ac2f4fb64c37f3f9ae533c661f186ec1763e6bb88907cd4c
\ No newline at end of file