From 3f632d5bd22432ac76647e43ae92bd498e29e05f Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Sat, 2 May 2009 10:03:09 +0000 Subject: [PATCH] When a cursor points at the last entry of an intkey btree after an insert, leave it there (instead of moving it to the tree root node). This speeds up statements of the form "INSERT INTO ... SELECT ..." that use auto-generated rowids. (CVS 6592) FossilOrigin-Name: 9950c0a79c82eb7d8495b0b1a8fe117d566e2387 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/btree.c | 53 +++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 22d417b81c..744628383e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sreset\sthe\scursor\sbefore\sseeking\sit\sin\ssqlite3BtreeInsert().\sThis\sspeeds\sup\sINSERT\soperations\sthat\suse\sauto-generated\srowid\svalues.\s(CVS\s6591) -D 2009-05-02T07:36:50 +C When\sa\scursor\spoints\sat\sthe\slast\sentry\sof\san\sintkey\sbtree\safter\san\sinsert,\sleave\sit\sthere\s(instead\sof\smoving\sit\sto\sthe\stree\sroot\snode).\sThis\sspeeds\sup\sstatements\sof\sthe\sform\s"INSERT\sINTO\s...\sSELECT\s..."\sthat\suse\sauto-generated\srowids.\s(CVS\s6592) +D 2009-05-02T10:03:09 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -106,7 +106,7 @@ F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/backup.c 0082d0e5a63f04e88faee0dff0a7d63d3e92a78d F src/bitvec.c ef370407e03440b0852d05024fb016b14a471d3d F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c -F src/btree.c 1201cba9e4ccd029a2b88431d14e315c086af6ba +F src/btree.c 64ad8841aefce2ba0cb3b138e5fe8669ce5fa6db F src/btree.h 99fcc7e8c4a1e35afe271bcb38de1a698dfc904e F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5 F src/build.c a079f965feea2d0b469b293e09cd0ac41be1272f @@ -727,7 +727,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 7d2b80c7addc2d03d49647da9c6df9113f01349d -R be37f24bb5752583479cd908d65ba960 +P 20c4acc291def33980f584f882c76e85ee1c8238 +R 473bd4e478192dc26a9afe58e69a17f0 U danielk1977 -Z 771348bde250b0527ce1a0ce0c034f60 +Z 5fda7c8bdbaa8fda519ae98860016fe1 diff --git a/manifest.uuid b/manifest.uuid index 81dae04fdc..e59e11086a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -20c4acc291def33980f584f882c76e85ee1c8238 \ No newline at end of file +9950c0a79c82eb7d8495b0b1a8fe117d566e2387 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 7241ac7b58..2692539a50 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.604 2009/05/02 07:36:50 danielk1977 Exp $ +** $Id: btree.c,v 1.605 2009/05/02 10:03:09 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -3921,6 +3921,22 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ assert( cursorHoldsMutex(pCur) ); assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) ); + + /* If the cursor already points to the last entry, this is a no-op. */ + if( CURSOR_VALID==pCur->eState && pCur->atLast ){ +#ifdef SQLITE_DEBUG + /* This block serves to assert() that the cursor really does point + ** to the last entry in the b-tree. */ + int ii; + for(ii=0; iiiPage; ii++){ + assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell ); + } + assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 ); + assert( pCur->apPage[pCur->iPage]->leaf ); +#endif + return SQLITE_OK; + } + rc = moveToRoot(pCur); if( rc==SQLITE_OK ){ if( CURSOR_INVALID==pCur->eState ){ @@ -6210,17 +6226,42 @@ int sqlite3BtreeInsert( assert( pPage->leaf ); } rc = insertCell(pPage, idx, newCell, szNew, 0, 0); - if( rc==SQLITE_OK ){ + assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); + + /* If no error has occured, call balance() to deal with any overflow and + ** move the cursor to point at the root of the table (since balance may + ** have rearranged the table in such a way as to invalidate BtCursor.apPage[] + ** or BtCursor.aiIdx[]). + ** + ** Except, if all of the following are true, do nothing: + ** + ** * Inserting the new cell did not cause overflow, + ** + ** * Before inserting the new cell the cursor was pointing at the + ** largest key in an intkey B-Tree, and + ** + ** * The key value associated with the new cell is now the largest + ** in the B-Tree. + ** + ** In this case the cursor can be safely left pointing at the (new) + ** largest key value in the B-Tree. Doing so speeds up inserting a set + ** of entries with increasing integer key values via a single cursor + ** (comes up with "INSERT INTO ... SELECT ..." statements), as + ** the next insert operation is not required to seek the cursor. + */ + if( rc==SQLITE_OK + && (pPage->nOverflow || !pCur->atLast || loc>=0 || !pCur->apPage[0]->intKey) + ){ rc = balance(pCur, 1); + if( rc==SQLITE_OK ){ + moveToRoot(pCur); + } } - + /* Must make sure nOverflow is reset to zero even if the balance() ** fails. Internal data structure corruption will result otherwise. */ pCur->apPage[pCur->iPage]->nOverflow = 0; - if( rc==SQLITE_OK ){ - moveToRoot(pCur); - } end_insert: return rc; } -- 2.47.2