From: drh Date: Fri, 25 May 2018 14:39:24 +0000 (+0000) Subject: This is an untested proof-of-concept for enhancements to RTree that attempt X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Frtree-update-optimization;p=thirdparty%2Fsqlite.git This is an untested proof-of-concept for enhancements to RTree that attempt 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 --- diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index e1b16ec0f5..fe6b38e8ae 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -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; iicell.aCoord[ii+1].f ){ @@ -3128,7 +3147,7 @@ static int rtreeUpdate( }else #endif { - for(ii=0; iicell.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; iinAux+pRtree->nDim2+3; iipWriteAux; 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; jjnAux; jj++){ sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]); } diff --git a/manifest b/manifest index 721b442bbb..13a162a28b 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 5d8567b91b..77b8e67cae 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b816023ce07d01024d5769e16db924374a49bf909edd12dc1344a0a1ef693db5 \ No newline at end of file +6f7cfeff708521a3ac2f4fb64c37f3f9ae533c661f186ec1763e6bb88907cd4c \ No newline at end of file