1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Omit the Reinsert algorithm from RTree. This causes most benchmarks to run

faster, at the expense of having a slightly less dense and hence larger index
(example: 33 entries/node versus 34 entries/node).

FossilOrigin-Name: b3049a1d3dbdd63c471499c2f6b417655defe9ad90228e7cc722f5be877aae01
This commit is contained in:
drh
2023-09-13 17:30:12 +00:00
parent f9967cb302
commit 7de8ae22f7
8 changed files with 33 additions and 203 deletions

View File

@ -1683,7 +1683,6 @@ static int geopolyUpdate(
}
if( rc==SQLITE_OK ){
int rc2;
pRtree->iReinsertHeight = -1;
rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0);
rc2 = nodeRelease(pRtree, pLeaf);
if( rc==SQLITE_OK ){

View File

@ -178,7 +178,6 @@ struct Rtree {
** headed by the node (leaf nodes have RtreeNode.iNode==0).
*/
RtreeNode *pDeleted;
int iReinsertHeight; /* Height of sub-trees Reinsert() has run on */
/* Blob I/O on xxx_node */
sqlite3_blob *pNodeBlob;
@ -2342,77 +2341,6 @@ static int parentWrite(Rtree *pRtree, sqlite3_int64 iNode, sqlite3_int64 iPar){
static int rtreeInsertCell(Rtree *, RtreeNode *, RtreeCell *, int);
/*
** Arguments aIdx, aDistance and aSpare all point to arrays of size
** nIdx. The aIdx array contains the set of integers from 0 to
** (nIdx-1) in no particular order. This function sorts the values
** in aIdx according to the indexed values in aDistance. For
** example, assuming the inputs:
**
** aIdx = { 0, 1, 2, 3 }
** aDistance = { 5.0, 2.0, 7.0, 6.0 }
**
** this function sets the aIdx array to contain:
**
** aIdx = { 0, 1, 2, 3 }
**
** The aSpare array is used as temporary working space by the
** sorting algorithm.
*/
static void SortByDistance(
int *aIdx,
int nIdx,
RtreeDValue *aDistance,
int *aSpare
){
if( nIdx>1 ){
int iLeft = 0;
int iRight = 0;
int nLeft = nIdx/2;
int nRight = nIdx-nLeft;
int *aLeft = aIdx;
int *aRight = &aIdx[nLeft];
SortByDistance(aLeft, nLeft, aDistance, aSpare);
SortByDistance(aRight, nRight, aDistance, aSpare);
memcpy(aSpare, aLeft, sizeof(int)*nLeft);
aLeft = aSpare;
while( iLeft<nLeft || iRight<nRight ){
if( iLeft==nLeft ){
aIdx[iLeft+iRight] = aRight[iRight];
iRight++;
}else if( iRight==nRight ){
aIdx[iLeft+iRight] = aLeft[iLeft];
iLeft++;
}else{
RtreeDValue fLeft = aDistance[aLeft[iLeft]];
RtreeDValue fRight = aDistance[aRight[iRight]];
if( fLeft<fRight ){
aIdx[iLeft+iRight] = aLeft[iLeft];
iLeft++;
}else{
aIdx[iLeft+iRight] = aRight[iRight];
iRight++;
}
}
}
#if 0
/* Check that the sort worked */
{
int jj;
for(jj=1; jj<nIdx; jj++){
RtreeDValue left = aDistance[aIdx[jj-1]];
RtreeDValue right = aDistance[aIdx[jj]];
assert( left<=right );
}
}
#endif
}
}
/*
** Arguments aIdx, aCell and aSpare all point to arrays of size
@ -2896,108 +2824,7 @@ static int deleteCell(Rtree *pRtree, RtreeNode *pNode, int iCell, int iHeight){
return rc;
}
static int Reinsert(
Rtree *pRtree,
RtreeNode *pNode,
RtreeCell *pCell,
int iHeight
){
int *aOrder;
int *aSpare;
RtreeCell *aCell;
RtreeDValue *aDistance;
int nCell;
RtreeDValue aCenterCoord[RTREE_MAX_DIMENSIONS];
int iDim;
int ii;
int rc = SQLITE_OK;
int n;
memset(aCenterCoord, 0, sizeof(RtreeDValue)*RTREE_MAX_DIMENSIONS);
nCell = NCELL(pNode)+1;
n = (nCell+1)&(~1);
/* Allocate the buffers used by this operation. The allocation is
** relinquished before this function returns.
*/
aCell = (RtreeCell *)sqlite3_malloc64(n * (
sizeof(RtreeCell) + /* aCell array */
sizeof(int) + /* aOrder array */
sizeof(int) + /* aSpare array */
sizeof(RtreeDValue) /* aDistance array */
));
if( !aCell ){
return SQLITE_NOMEM;
}
aOrder = (int *)&aCell[n];
aSpare = (int *)&aOrder[n];
aDistance = (RtreeDValue *)&aSpare[n];
for(ii=0; ii<nCell; ii++){
if( ii==(nCell-1) ){
memcpy(&aCell[ii], pCell, sizeof(RtreeCell));
}else{
nodeGetCell(pRtree, pNode, ii, &aCell[ii]);
}
aOrder[ii] = ii;
for(iDim=0; iDim<pRtree->nDim; iDim++){
aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2]);
aCenterCoord[iDim] += DCOORD(aCell[ii].aCoord[iDim*2+1]);
}
}
for(iDim=0; iDim<pRtree->nDim; iDim++){
aCenterCoord[iDim] = (aCenterCoord[iDim]/(nCell*(RtreeDValue)2));
}
for(ii=0; ii<nCell; ii++){
aDistance[ii] = RTREE_ZERO;
for(iDim=0; iDim<pRtree->nDim; iDim++){
RtreeDValue coord = (DCOORD(aCell[ii].aCoord[iDim*2+1]) -
DCOORD(aCell[ii].aCoord[iDim*2]));
aDistance[ii] += (coord-aCenterCoord[iDim])*(coord-aCenterCoord[iDim]);
}
}
SortByDistance(aOrder, nCell, aDistance, aSpare);
nodeZero(pRtree, pNode);
for(ii=0; rc==SQLITE_OK && ii<(nCell-(RTREE_MINCELLS(pRtree)+1)); ii++){
RtreeCell *p = &aCell[aOrder[ii]];
nodeInsertCell(pRtree, pNode, p);
if( p->iRowid==pCell->iRowid ){
if( iHeight==0 ){
rc = rowidWrite(pRtree, p->iRowid, pNode->iNode);
}else{
rc = parentWrite(pRtree, p->iRowid, pNode->iNode);
}
}
}
if( rc==SQLITE_OK ){
rc = fixBoundingBox(pRtree, pNode);
}
for(; rc==SQLITE_OK && ii<nCell; ii++){
/* Find a node to store this cell in. pNode->iNode currently contains
** the height of the sub-tree headed by the cell.
*/
RtreeNode *pInsert;
RtreeCell *p = &aCell[aOrder[ii]];
rc = ChooseLeaf(pRtree, p, iHeight, &pInsert);
if( rc==SQLITE_OK ){
int rc2;
rc = rtreeInsertCell(pRtree, pInsert, p, iHeight);
rc2 = nodeRelease(pRtree, pInsert);
if( rc==SQLITE_OK ){
rc = rc2;
}
}
}
sqlite3_free(aCell);
return rc;
}
/*
** Insert cell pCell into node pNode. Node pNode is the head of a
** subtree iHeight high (leaf nodes have iHeight==0).
@ -3018,12 +2845,7 @@ static int rtreeInsertCell(
}
}
if( nodeInsertCell(pRtree, pNode, pCell) ){
if( iHeight<=pRtree->iReinsertHeight || pNode->iNode==1 ){
rc = SplitNode(pRtree, pNode, pCell, iHeight);
}else{
pRtree->iReinsertHeight = iHeight;
rc = Reinsert(pRtree, pNode, pCell, iHeight);
}
rc = SplitNode(pRtree, pNode, pCell, iHeight);
}else{
rc = AdjustTree(pRtree, pNode, pCell);
if( ALWAYS(rc==SQLITE_OK) ){
@ -3366,7 +3188,6 @@ static int rtreeUpdate(
}
if( rc==SQLITE_OK ){
int rc2;
pRtree->iReinsertHeight = -1;
rc = rtreeInsertCell(pRtree, pLeaf, &cell, 0);
rc2 = nodeRelease(pRtree, pLeaf);
if( rc==SQLITE_OK ){

View File

@ -75,7 +75,7 @@ do_test rtree8-1.2.2 { nested_select 1 } {51}
#
populate_t1 1500
do_rtree_integrity_test rtree8-1.3.0 t1
do_execsql_test rtree8-1.3.1 { SELECT max(nodeno) FROM t1_node } {164}
do_execsql_test rtree8-1.3.1 { SELECT max(nodeno) FROM t1_node } {183}
do_test rtree8-1.3.2 {
set rowids [execsql {SELECT min(rowid) FROM t1_rowid GROUP BY nodeno}]
set stmt_list [list]

View File

@ -113,7 +113,7 @@ do_execsql_test rtreeA-1.1.1 {
SELECT rtreecheck('main', 't1')
} {{Node 1 missing from database
Wrong number of entries in %_rowid table - expected 0, actual 500
Wrong number of entries in %_parent table - expected 0, actual 23}}
Wrong number of entries in %_parent table - expected 0, actual 25}}
do_execsql_test rtreeA-1.2.0 { DROP TABLE t1_node } {}
do_corruption_tests rtreeA-1.2 -error "database disk image is malformed" {
@ -191,7 +191,7 @@ do_execsql_test rtreeA-3.3.3.4 {
SELECT rtreecheck('main', 't1')
} {{Rtree depth out of range (65535)
Wrong number of entries in %_rowid table - expected 0, actual 499
Wrong number of entries in %_parent table - expected 0, actual 23}}
Wrong number of entries in %_parent table - expected 0, actual 25}}
#-------------------------------------------------------------------------
# Set the "number of entries" field on some nodes incorrectly.

View File

@ -601,11 +601,21 @@ do_execsql_test 2.5.2 {
SELECT A.id FROM demo_index AS A, demo_index AS B
WHERE A.maxX>=B.minX AND A.minX<=B.maxX
AND A.maxY>=B.minY AND A.minY<=B.maxY
AND B.id=28269;
AND B.id=28269 ORDER BY +A.id;
} {
28293 28216 28322 28286 28269
28215 28336 28262 28291 28320
28313 28298 28287
28215
28216
28262
28269
28286
28287
28291
28293
28298
28313
28320
28322
28336
}
# EVIDENCE-OF: R-02723-34107 Note that it is not necessary for all
@ -1575,7 +1585,7 @@ execsql BEGIN
do_test 3.6 {
execsql { INSERT INTO rt2_parent VALUES(1000, 1000) }
execsql { SELECT rtreecheck('rt2') }
} {{Wrong number of entries in %_parent table - expected 9, actual 10}}
} {{Wrong number of entries in %_parent table - expected 10, actual 11}}
execsql ROLLBACK

View File

@ -1043,7 +1043,7 @@ do_test rtreefuzz001-500 {
| end crash-2e81f5dce5cbd4.db}]
execsql { PRAGMA writable_schema = 1;}
catchsql {UPDATE t1 SET ex= ex ISNULL}
} {1 {database disk image is malformed}}
} {0 {}}
do_test rtreefuzz001-600 {
sqlite3 db {}

View File

@ -1,5 +1,5 @@
C Performance\soptimization\sto\scellContains()\sin\sRTREE.
D 2023-09-13T14:07:07.116
C Omit\sthe\sReinsert\salgorithm\sfrom\sRTree.\s\sThis\scauses\smost\sbenchmarks\sto\srun\nfaster,\sat\sthe\sexpense\sof\shaving\sa\sslightly\sless\sdense\sand\shence\slarger\sindex\n(example:\s33\sentries/node\sversus\s34\sentries/node).
D 2023-09-13T17:30:12.131
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -470,8 +470,8 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/geopoly.c 971e0b5bd9adaf0811feb8c0842a310811159da10319eb0e74fdb42bf26b99ca
F ext/rtree/rtree.c 461502ef5fa031e5fc7837377b23bfae24934414a88f6bf5505921864aae788f
F ext/rtree/geopoly.c 41cb6e6a43d986f374e7845c3229252b5811c53ce2382a24b48cc9370916cdd8
F ext/rtree/rtree.c 330ebe35d16528973b990b3d392a5627ae240de5bfc3c8fddb64aa6548ad7308
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test 877d40b8b61b1f88cec9d4dc0ff8334f5b05299fac12a35141532e2881860e9d
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@ -480,9 +480,9 @@ F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
F ext/rtree/rtree6.test 2f5ffc69670395c1a84fad7924e2d49e82a25460c5293fb1e54e1aa906f04945
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
F ext/rtree/rtree8.test 2d99006a1386663978c9e1df167554671e4f711c419175b39f332719deb1ce0e
F ext/rtree/rtree8.test 4da84c7f328bbdca15052fa13da6e8b8d426433347bf75fc85574c2f5a411a02
F ext/rtree/rtree9.test fd3c9384ef8aabbc127b3878764070398f136eebc551cd20484b570f2cc1956a
F ext/rtree/rtreeA.test a7fd235d8194115fa2e14d300337931eb2e960fe8a46cdfb66add2206412ea41
F ext/rtree/rtreeA.test 14e67fccc5b41efbad7ea99d21d11aaa66d2067da7d5b296ee86e4de64391d82
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
F ext/rtree/rtreeC.test 2978b194d09b13e106bdb0e1c5b408b9d42eb338c1082bf43c87ef43bd626147
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
@ -496,10 +496,10 @@ F ext/rtree/rtree_util.tcl 202ca70df1f0645ef9d5a2170e62d378a28098d9407f0569e85c9
F ext/rtree/rtreecheck.test 934546ad9b563e090ee0c5cbdc69ad014189ad76e5df7320526797a9a345661f
F ext/rtree/rtreecirc.test aec664eb21ae943aeb344191407afff5d392d3ae9d12b9a112ced0d9c5de298e
F ext/rtree/rtreeconnect.test 225ad3fcb483d36cbee423a25052a6bbae762c9576ae9268332360c68c170d3d
F ext/rtree/rtreedoc.test 27a5703cb1200f6f69051de68da546cef3dfdcf59be73afadfc50b9f9c9960d9
F ext/rtree/rtreedoc.test d633982d61542f3bc0a0a2df0382a02cc699ac56cbda01130cde6da44a228490
F ext/rtree/rtreedoc2.test 194ebb7d561452dcdc10bf03f44e30c082c2f0c14efeb07f5e02c7daf8284d93
F ext/rtree/rtreedoc3.test 555a878c4d79c4e37fa439a1c3b02ee65d3ebaf75d9e8d96a9c55d66db3efbf8
F ext/rtree/rtreefuzz001.test 0fc793f67897c250c5fde96cefee455a5e2fb92f4feeabde5b85ea02040790ee
F ext/rtree/rtreefuzz001.test 44f680a23dbe00d1061dbde381d711119099846d166580c4381e402b9d62cb74
F ext/rtree/sqlite3rtree.h 03c8db3261e435fbddcfc961471795cbf12b24e03001d0015b2636b0f3881373
F ext/rtree/test_rtreedoc.c de76b3472bc74b788d079342fdede22ff598796dd3d97acffe46e09228af83a3
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
@ -2119,8 +2119,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 59f0e239d19393190911ea3bd89b5a24be0d85d64ccf51906efc9537ad5d7298
R e9b5b4a1842b9ceb8d187565fea4e7e6
P 43cde22bf3f36687df231eddf642581d1d4f4102ad8568d31f5b2ff0302ca800
R e036488f26ef70cc75ddea68bb4fe9e6
U drh
Z cf6aeb5bc7687975d4feb7bd21780d1c
Z 0b10c745997362c35710ad8da28ad415
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
43cde22bf3f36687df231eddf642581d1d4f4102ad8568d31f5b2ff0302ca800
b3049a1d3dbdd63c471499c2f6b417655defe9ad90228e7cc722f5be877aae01