From 428ae8cb415c4b90330ccdbb5aed01442b0c1f0d Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 4 Jan 2003 16:48:09 +0000 Subject: [PATCH] Optimizations to the BTree module for a modest speed improvement. (CVS 810) FossilOrigin-Name: 39902a70417475225956704a037493515e9b08b9 --- manifest | 14 +++++----- manifest.uuid | 2 +- src/btree.c | 70 ++++++++++++++++++++++++++++++++++++++----------- test/table.test | 4 +-- 4 files changed, 64 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index 3d500a6c05..0798b218f1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Allow\sthe\srollback\sjournal\sto\sbe\sempty\sexcept\sfor\sits\sheader.\nTicket\s#212.\s(CVS\s809) -D 2003-01-03T02:04:27 +C Optimizations\sto\sthe\sBTree\smodule\sfor\sa\smodest\sspeed\simprovement.\s(CVS\s810) +D 2003-01-04T16:48:09 F Makefile.in 868c17a1ae1c07603d491274cc8f86c04acf2a1e F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -18,7 +18,7 @@ F main.mk 9d13839b9697af332d788fe6e801e68da027cc5c F publish.sh e5b83867d14708ed58cec8cba0a4f201e969474d F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea -F src/btree.c 6a2a9bb701a60df4abe2fb7047b25787c90e1ffd +F src/btree.c 4ed13ad0c695e4fb803d106926c6fdd08a0b4d0f F src/btree.h 17710339f7a8f46e3c7d6d0d4648ef19c584ffda F src/build.c 8569ac014609add4b796260d3567a5090b90056d F src/delete.c aad9d4051ab46e6f6391ea5f7b8994a7c05bdd15 @@ -100,7 +100,7 @@ F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85 F test/sort.test 876b76c5a837af5bead713146c7c65f85e84fbf5 F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f -F test/table.test 10508e5e53fb7971b9fa6acb29d85748e545745c +F test/table.test 2a94f55b39008daa79b81f37aaf7be81386ca71e F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6 F test/tclsqlite.test 2441ab135e5af85110326b3e3b057e7257c144e1 F test/temptable.test 03b7bdb7d6ce2c658ad20c94b037652c6cad34e0 @@ -152,7 +152,7 @@ F www/speed.tcl a20a792738475b68756ea7a19321600f23d1d803 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P db745e87dc26cf1a35cdcec18f4b659742e14120 -R a2eb3af8e1d5fb0a64abc7b1644d24dd +P 1ba41bc2afab18cc295d9a45845296b46bfa57e5 +R a4125fbf39c245763f99492b33c9c8e8 U drh -Z 3fb10791064333a0f71d6fcfe3547d9c +Z df8ce8a4e13ca11e4b128387a80bf533 diff --git a/manifest.uuid b/manifest.uuid index 5dff4bb2a8..8a7d282172 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1ba41bc2afab18cc295d9a45845296b46bfa57e5 \ No newline at end of file +39902a70417475225956704a037493515e9b08b9 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index f34e972626..cc178c9644 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.76 2003/01/02 14:43:56 drh Exp $ +** $Id: btree.c,v 1.77 2003/01/04 16:48:09 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -319,11 +319,13 @@ struct MemPage { char aDisk[SQLITE_PAGE_SIZE]; /* Page data stored on disk */ PageHdr hdr; /* Overlay page header */ } u; - int isInit; /* True if auxiliary data is initialized */ + u8 isInit; /* True if auxiliary data is initialized */ + u8 idxShift; /* True if apCell[] indices have changed */ + u8 isOverfull; /* Some apCell[] points outside u.aDisk[] */ MemPage *pParent; /* The parent of this page. NULL for root */ + int idxParent; /* Index in pParent->apCell[] of this node */ int nFree; /* Number of free bytes in u.aDisk[] */ int nCell; /* Number of entries on this page */ - int isOverfull; /* Some apCell[] points outside u.aDisk[] */ Cell *apCell[MX_CELL+2]; /* All data entires in sorted order */ }; @@ -1347,6 +1349,12 @@ static int moveToChild(BtCursor *pCur, int newPgno){ if( rc ) return rc; rc = initPage(pBt, pNewPage, newPgno, pCur->pPage); if( rc ) return rc; + assert( pCur->idx>=pCur->pPage->nCell + || pCur->pPage->apCell[pCur->idx]->h.leftChild==SWAB32(pBt,newPgno) ); + assert( pCur->idxpPage->nCell + || pCur->pPage->u.hdr.rightChild==SWAB32(pBt,newPgno) ); + pNewPage->idxParent = pCur->idx; + pCur->pPage->idxShift = 0; sqlitepager_unref(pCur->pPage); pCur->pPage = pNewPage; pCur->idx = 0; @@ -1364,19 +1372,42 @@ static int moveToChild(BtCursor *pCur, int newPgno){ static int moveToParent(BtCursor *pCur){ Pgno oldPgno; MemPage *pParent; - int i; + int idxParent; pParent = pCur->pPage->pParent; if( pParent==0 ) return SQLITE_INTERNAL; + idxParent = pCur->pPage->idxParent; oldPgno = sqlitepager_pagenumber(pCur->pPage); sqlitepager_ref(pParent); sqlitepager_unref(pCur->pPage); pCur->pPage = pParent; - pCur->idx = pParent->nCell; - oldPgno = SWAB32(pCur->pBt, oldPgno); - for(i=0; inCell; i++){ - if( pParent->apCell[i]->h.leftChild==oldPgno ){ - pCur->idx = i; - break; + assert( pParent->idxShift==0 ); + if( pParent->idxShift==0 ){ + pCur->idx = idxParent; +#ifndef NDEBUG + /* Verify that pCur->idx is the correct index to point back to the child + ** page we just came from + */ + oldPgno = SWAB32(pCur->pBt, oldPgno); + if( pCur->idxnCell ){ + assert( pParent->apCell[idxParent]->h.leftChild==oldPgno ); + }else{ + assert( pParent->u.hdr.rightChild==oldPgno ); + } +#endif + }else{ + /* The MemPage.idxShift flag indicates that cell indices might have + ** changed since idxParent was set and hence idxParent might be out + ** of date. So recompute the parent cell index by scanning all cells + ** and locating the one that points to the child we just came from. + */ + int i; + pCur->idx = pParent->nCell; + oldPgno = SWAB32(pCur->pBt, oldPgno); + for(i=0; inCell; i++){ + if( pParent->apCell[i]->h.leftChild==oldPgno ){ + pCur->idx = i; + break; + } } } return SQLITE_OK; @@ -1427,6 +1458,7 @@ static int moveToRightmost(BtCursor *pCur){ int rc; while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){ + pCur->idx = pCur->pPage->nCell; rc = moveToChild(pCur, SWAB32(pCur->pBt, pgno)); if( rc ) return rc; } @@ -1536,6 +1568,7 @@ int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){ if( pRes ) *pRes = c; return SQLITE_OK; } + pCur->idx = lwr; rc = moveToChild(pCur, SWAB32(pCur->pBt, chldPg)); if( rc ) return rc; } @@ -1887,7 +1920,7 @@ static int fillInCell( ** given in the second argument so that MemPage.pParent holds the ** pointer in the third argument. */ -static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent){ +static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent,int idx){ MemPage *pThis; if( pgno==0 ) return; @@ -1899,6 +1932,7 @@ static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent){ pThis->pParent = pNewParent; if( pNewParent ) sqlitepager_ref(pNewParent); } + pThis->idxParent = idx; sqlitepager_unref(pThis); } } @@ -1915,9 +1949,10 @@ static void reparentChildPages(Btree *pBt, MemPage *pPage){ int i; Pager *pPager = pBt->pPager; for(i=0; inCell; i++){ - reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage); + reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage, i); } - reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage); + reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage, i); + pPage->idxShift = 0; } /* @@ -1943,6 +1978,7 @@ static void dropCell(Btree *pBt, MemPage *pPage, int idx, int sz){ pPage->apCell[j] = pPage->apCell[j+1]; } pPage->nCell--; + pPage->idxShift = 1; } /* @@ -1975,6 +2011,7 @@ static void insertCell(Btree *pBt, MemPage *pPage, int i, Cell *pCell, int sz){ memcpy(&pPage->u.aDisk[idx], pCell, sz); pPage->apCell[i] = (Cell*)&pPage->u.aDisk[idx]; } + pPage->idxShift = 1; } /* @@ -2161,6 +2198,7 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){ assert( sqlitepager_iswriteable(pChild) ); copyPage(pChild, pPage); pChild->pParent = pPage; + pChild->idxParent = pChild->nCell; sqlitepager_ref(pPage); pChild->isOverfull = 1; if( pCur && pCur->pPage==pPage ){ @@ -2195,9 +2233,8 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){ if( idx<0 && pParent->u.hdr.rightChild==swabPgno ){ idx = pParent->nCell; } - if( idx<0 ){ - return SQLITE_CORRUPT; - } + assert( idx>=0 ); + /* assert( pParent->idxShift || idx==pPage->idxParent ); */ /* ** Initialize variables so that it will be safe to jump @@ -2235,6 +2272,7 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){ if( rc ) goto balance_cleanup; rc = initPage(pBt, apOld[i], pgnoOld[i], pParent); if( rc ) goto balance_cleanup; + apOld[i]->idxParent = k; nOld++; } diff --git a/test/table.test b/test/table.test index 8bed034a9b..adad1567c5 100644 --- a/test/table.test +++ b/test/table.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # -# $Id: table.test,v 1.20 2002/08/31 18:53:09 drh Exp $ +# $Id: table.test,v 1.21 2003/01/04 16:48:10 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -217,9 +217,9 @@ set r {} for {set i 1} {$i<=100} {incr i 2} { lappend r [format test%03d $i] } -#execsql {--vdbe-trace-on--} do_test table-4.2 { for {set i 2} {$i<=100} {incr i 2} { + # if {$i==38} {execsql {pragma vdbe_trace=on}} set sql "DROP TABLE [format TEST%03d $i]" execsql $sql }