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:
36
src/btree.c
36
src/btree.c
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user