Compare commits

...

1 Commits

Author SHA1 Message Date
drh 470f17e8d9 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
2018-05-25 14:39:24 +00:00
3 changed files with 75 additions and 29 deletions
+65 -22
View 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]);
}
+9 -6
View File
@@ -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
+1 -1
View File
@@ -1 +1 @@
b816023ce07d01024d5769e16db924374a49bf909edd12dc1344a0a1ef693db5
6f7cfeff708521a3ac2f4fb64c37f3f9ae533c661f186ec1763e6bb88907cd4c