1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Fix multiple performance regressions (ticket #2298 among them)

and add tests to make sure they do not come back. (CVS 3839)

FossilOrigin-Name: 32bb2d5859906b4fb0f6083eedd7f3a81b9cf5e2
This commit is contained in:
drh
2007-04-13 02:14:30 +00:00
parent 994c80af27
commit 538f570cd1
9 changed files with 339 additions and 98 deletions

View File

@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.354 2007/04/09 12:45:03 drh Exp $
** $Id: btree.c,v 1.355 2007/04/13 02:14:30 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -1396,13 +1396,20 @@ static void zeroPage(MemPage *pPage, int flags){
/*
** Get a page from the pager. Initialize the MemPage.pBt and
** MemPage.aData elements if needed.
**
** If the noContent flag is set, it means that we do not care about
** the content of the page at this time. So do not go to the disk
** to fetch the content. Just fill in the content with zeros for now.
** If in the future we call sqlite3PagerWrite() on this page, that
** means we have started to be concerned about content and the disk
** read should occur at that point.
*/
static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage, int clrFlag){
static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage, int noContent){
int rc;
MemPage *pPage;
DbPage *pDbPage;
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, clrFlag);
rc = sqlite3PagerAcquire(pBt->pPager, pgno, (DbPage**)&pDbPage, noContent);
if( rc ) return rc;
pPage = (MemPage *)sqlite3PagerGetExtra(pDbPage);
pPage->aData = sqlite3PagerGetData(pDbPage);
@@ -1411,9 +1418,6 @@ static int getPage(BtShared *pBt, Pgno pgno, MemPage **ppPage, int clrFlag){
pPage->pgno = pgno;
pPage->hdrOffset = pPage->pgno==1 ? 100 : 0;
*ppPage = pPage;
if( clrFlag ){
sqlite3PagerDontRollback(pPage->pDbPage);
}
return SQLITE_OK;
}
@@ -3830,6 +3834,7 @@ static int allocateBtreePage(
put4byte(&aData[4], k-1);
rc = getPage(pBt, *pPgno, ppPage, 1);
if( rc==SQLITE_OK ){
sqlite3PagerDontRollback((*ppPage)->pDbPage);
rc = sqlite3PagerWrite((*ppPage)->pDbPage);
if( rc!=SQLITE_OK ){
releasePage(*ppPage);
@@ -3948,7 +3953,7 @@ static int freePage(MemPage *pPage){
put4byte(&pTrunk->aData[4], k+1);
put4byte(&pTrunk->aData[8+k*4], pPage->pgno);
#ifndef SQLITE_SECURE_DELETE
sqlite3PagerDontWrite(pBt->pPager, pPage->pgno);
sqlite3PagerDontWrite(pPage->pDbPage);
#endif
}
TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno));
@@ -3982,7 +3987,7 @@ static int clearCell(MemPage *pPage, unsigned char *pCell){
if( ovflPgno==0 || ovflPgno>sqlite3PagerPagecount(pBt->pPager) ){
return SQLITE_CORRUPT_BKPT;
}
rc = getPage(pBt, ovflPgno, &pOvfl, 0);
rc = getPage(pBt, ovflPgno, &pOvfl, nOvfl==0);
if( rc ) return rc;
if( nOvfl ){
ovflPgno = get4byte(pOvfl->aData);
@@ -6561,18 +6566,31 @@ int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
rc = sqlite3PagerOverwrite(pBtTo->pPager, i, sqlite3PagerGetData(pDbPage));
sqlite3PagerUnref(pDbPage);
}
/* If the file is shrinking, journal the pages that are being truncated
** so that they can be rolled back if the commit fails.
*/
for(i=nPage+1; rc==SQLITE_OK && i<=nToPage; i++){
DbPage *pDbPage;
if( i==iSkip ) continue;
rc = sqlite3PagerGet(pBtTo->pPager, i, &pDbPage);
if( rc ) break;
rc = sqlite3PagerWrite(pDbPage);
sqlite3PagerDontWrite(pDbPage);
/* Yeah. It seems wierd to call DontWrite() right after Write(). But
** that is because the names of those procedures do not exactly
** represent what they do. Write() really means "put this page in the
** rollback journal and mark it as dirty so that it will be written
** to the database file later." DontWrite() undoes the second part of
** that and prevents the page from being written to the database. The
** page is still on the rollback journal, though. And that is the whole
** point of this loop: to put pages on the rollback journal. */
sqlite3PagerUnref(pDbPage);
sqlite3PagerDontWrite(pBtTo->pPager, i);
}
if( !rc && nPage<nToPage ){
rc = sqlite3PagerTruncate(pBtTo->pPager, nPage);
}
if( rc ){
sqlite3BtreeRollback(pTo);
}