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:
@ -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 ){
|
||||
|
@ -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 ){
|
||||
|
@ -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]
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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 {}
|
||||
|
Reference in New Issue
Block a user