OLD | NEW |
(Empty) | |
| 1 From d62ff0d64a8738fd8bb07b82bcebd65143a17045 Mon Sep 17 00:00:00 2001 |
| 2 From: Scott Hess <shess@chromium.org> |
| 3 Date: Thu, 2 Mar 2017 15:23:09 -0800 |
| 4 Subject: [PATCH 11/11] Allow auto-vacuum to work with chunks. |
| 5 |
| 6 SQLITE_FCNTL_CHUNK_SIZE can advise the VFS to resize files in quantum |
| 7 amounts, to reduce fragmentation from tiny appends. This change allows |
| 8 a new PRAGMA auto_vacuum_slack_pages to provide auto_vacuum with a hint |
| 9 to only rearrange pages when an entire quantum can be released. |
| 10 |
| 11 BUG=698010 |
| 12 --- |
| 13 third_party/sqlite/src/src/btree.c | 56 ++++++++++++++++++++++++++++++++++- |
| 14 third_party/sqlite/src/src/btree.h | 2 ++ |
| 15 third_party/sqlite/src/src/btreeInt.h | 1 + |
| 16 third_party/sqlite/src/src/pragma.c | 21 +++++++++++++ |
| 17 third_party/sqlite/src/src/pragma.h | 8 +++++ |
| 18 5 files changed, 87 insertions(+), 1 deletion(-) |
| 19 |
| 20 diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btr
ee.c |
| 21 index de553423b884..3335ced417ca 100644 |
| 22 --- a/third_party/sqlite/src/src/btree.c |
| 23 +++ b/third_party/sqlite/src/src/btree.c |
| 24 @@ -2812,6 +2812,46 @@ int sqlite3BtreeGetAutoVacuum(Btree *p){ |
| 25 #endif |
| 26 } |
| 27 |
| 28 +/* |
| 29 +** Change the 'auto-vacuum-slack-pages' property of the database. If auto vacuu
m |
| 30 +** is enabled, this is the number of chunks of slack to allow before |
| 31 +** automatically running an incremental vacuum. |
| 32 +*/ |
| 33 +int sqlite3BtreeSetAutoVacuumSlackPages(Btree *p, int autoVacuumSlack){ |
| 34 +#ifdef SQLITE_OMIT_AUTOVACUUM |
| 35 + return SQLITE_READONLY; |
| 36 +#else |
| 37 + BtShared *pBt = p->pBt; |
| 38 + int rc = SQLITE_OK; |
| 39 + u8 avs = (u8)autoVacuumSlack; |
| 40 + if( autoVacuumSlack>avs ){ |
| 41 + avs = 0xFF; |
| 42 + } |
| 43 + |
| 44 + sqlite3BtreeEnter(p); |
| 45 + pBt->autoVacuumSlack = avs; |
| 46 + sqlite3BtreeLeave(p); |
| 47 + return rc; |
| 48 +#endif |
| 49 +} |
| 50 + |
| 51 +/* |
| 52 +** Return the value of the 'auto-vacuum-slack-pages' property. |
| 53 +*/ |
| 54 +int sqlite3BtreeGetAutoVacuumSlackPages(Btree *p){ |
| 55 +#ifdef SQLITE_OMIT_AUTOVACUUM |
| 56 + return 0; |
| 57 +#else |
| 58 + int rc = 0; |
| 59 + sqlite3BtreeEnter(p); |
| 60 + if( p->pBt->autoVacuum!=0 ){ |
| 61 + rc = p->pBt->autoVacuumSlack; |
| 62 + } |
| 63 + sqlite3BtreeLeave(p); |
| 64 + return rc; |
| 65 +#endif |
| 66 +} |
| 67 + |
| 68 |
| 69 /* |
| 70 ** Get a reference to pPage1 of the database file. This will |
| 71 @@ -3653,13 +3693,27 @@ int sqlite3BtreeIncrVacuum(Btree *p){ |
| 72 */ |
| 73 static int autoVacuumCommit(BtShared *pBt){ |
| 74 int rc = SQLITE_OK; |
| 75 + int bShouldVacuum = pBt->autoVacuum && !pBt->incrVacuum; |
| 76 Pager *pPager = pBt->pPager; |
| 77 VVA_ONLY( int nRef = sqlite3PagerRefcount(pPager); ) |
| 78 |
| 79 assert( sqlite3_mutex_held(pBt->mutex) ); |
| 80 invalidateAllOverflowCache(pBt); |
| 81 assert(pBt->autoVacuum); |
| 82 - if( !pBt->incrVacuum ){ |
| 83 + if( bShouldVacuum && pBt->autoVacuumSlack ){ |
| 84 + Pgno nOrig; /* Database size before freeing */ |
| 85 + Pgno nFree; /* Number of pages on the freelist initially */ |
| 86 + |
| 87 + nOrig = btreePagecount(pBt); |
| 88 + nFree = get4byte(&pBt->pPage1->aData[36]); |
| 89 + bShouldVacuum = |
| 90 + (nOrig-nFree-1)/pBt->autoVacuumSlack < (nOrig-1)/pBt->autoVacuumSlack; |
| 91 + /* TODO: When integrating this test with the following code, contrive to |
| 92 + ** trim to the integral chunk boundary, rather than trimming the entire fre
e |
| 93 + ** list. |
| 94 + */ |
| 95 + } |
| 96 + if( bShouldVacuum ){ |
| 97 Pgno nFin; /* Number of pages in database after autovacuuming */ |
| 98 Pgno nFree; /* Number of pages on the freelist initially */ |
| 99 Pgno iFree; /* The next page to be freed */ |
| 100 diff --git a/third_party/sqlite/src/src/btree.h b/third_party/sqlite/src/src/btr
ee.h |
| 101 index ae57468e3fd5..e0da44957564 100644 |
| 102 --- a/third_party/sqlite/src/src/btree.h |
| 103 +++ b/third_party/sqlite/src/src/btree.h |
| 104 @@ -78,6 +78,8 @@ int sqlite3BtreeGetOptimalReserve(Btree*); |
| 105 int sqlite3BtreeGetReserveNoMutex(Btree *p); |
| 106 int sqlite3BtreeSetAutoVacuum(Btree *, int); |
| 107 int sqlite3BtreeGetAutoVacuum(Btree *); |
| 108 +int sqlite3BtreeSetAutoVacuumSlackPages(Btree *, int); |
| 109 +int sqlite3BtreeGetAutoVacuumSlackPages(Btree *); |
| 110 int sqlite3BtreeBeginTrans(Btree*,int); |
| 111 int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster); |
| 112 int sqlite3BtreeCommitPhaseTwo(Btree*, int); |
| 113 diff --git a/third_party/sqlite/src/src/btreeInt.h b/third_party/sqlite/src/src/
btreeInt.h |
| 114 index b01163c33f49..eb9d1b5ef58d 100644 |
| 115 --- a/third_party/sqlite/src/src/btreeInt.h |
| 116 +++ b/third_party/sqlite/src/src/btreeInt.h |
| 117 @@ -412,6 +412,7 @@ struct BtShared { |
| 118 u8 openFlags; /* Flags to sqlite3BtreeOpen() */ |
| 119 #ifndef SQLITE_OMIT_AUTOVACUUM |
| 120 u8 autoVacuum; /* True if auto-vacuum is enabled */ |
| 121 + u8 autoVacuumSlack; /* Optional pages of slack for auto-vacuum */ |
| 122 u8 incrVacuum; /* True if incr-vacuum is enabled */ |
| 123 u8 bDoTruncate; /* True to truncate db on commit */ |
| 124 #endif |
| 125 diff --git a/third_party/sqlite/src/src/pragma.c b/third_party/sqlite/src/src/pr
agma.c |
| 126 index b1775a4082a3..1d5ebfca098d 100644 |
| 127 --- a/third_party/sqlite/src/src/pragma.c |
| 128 +++ b/third_party/sqlite/src/src/pragma.c |
| 129 @@ -736,6 +736,27 @@ void sqlite3Pragma( |
| 130 } |
| 131 #endif |
| 132 |
| 133 + /* |
| 134 + ** PRAGMA [schema.]auto_vacuum_slack_pages(N) |
| 135 + ** |
| 136 + ** Control chunk size of auto-vacuum. |
| 137 + */ |
| 138 +#ifndef SQLITE_OMIT_AUTOVACUUM |
| 139 + case PragTyp_AUTO_VACUUM_SLACK_PAGES: { |
| 140 + Btree *pBt = pDb->pBt; |
| 141 + assert( pBt!=0 ); |
| 142 + if( !zRight ){ |
| 143 + returnSingleInt(v, sqlite3BtreeGetAutoVacuumSlackPages(pBt)); |
| 144 + }else{ |
| 145 + int nPages = 8; |
| 146 + if( sqlite3GetInt32(zRight, &nPages) ){ |
| 147 + sqlite3BtreeSetAutoVacuumSlackPages(pBt, nPages); |
| 148 + } |
| 149 + } |
| 150 + break; |
| 151 + } |
| 152 +#endif |
| 153 + |
| 154 #ifndef SQLITE_OMIT_PAGER_PRAGMAS |
| 155 /* |
| 156 ** PRAGMA [schema.]cache_size |
| 157 diff --git a/third_party/sqlite/src/src/pragma.h b/third_party/sqlite/src/src/pr
agma.h |
| 158 index 5d8d0aa35b3f..e47f80fefac4 100644 |
| 159 --- a/third_party/sqlite/src/src/pragma.h |
| 160 +++ b/third_party/sqlite/src/src/pragma.h |
| 161 @@ -48,6 +48,7 @@ |
| 162 #define PragTyp_REKEY 40 |
| 163 #define PragTyp_LOCK_STATUS 41 |
| 164 #define PragTyp_PARSER_TRACE 42 |
| 165 +#define PragTyp_AUTO_VACUUM_SLACK_PAGES 43 |
| 166 |
| 167 /* Property flags associated with various pragma. */ |
| 168 #define PragFlg_NeedSchema 0x01 /* Force schema load before running */ |
| 169 @@ -145,6 +146,13 @@ static const PragmaName aPragmaName[] = { |
| 170 /* ColNames: */ 0, 0, |
| 171 /* iArg: */ 0 }, |
| 172 #endif |
| 173 +#if !defined(SQLITE_OMIT_AUTOVACUUM) |
| 174 + { /* zName: */ "auto_vacuum_slack_pages", |
| 175 + /* ePragTyp: */ PragTyp_AUTO_VACUUM_SLACK_PAGES, |
| 176 + /* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragF
lg_NoColumns1, |
| 177 + /* ColNames: */ 0, 0, |
| 178 + /* iArg: */ 0 }, |
| 179 +#endif |
| 180 #if !defined(SQLITE_OMIT_FLAG_PRAGMAS) |
| 181 #if !defined(SQLITE_OMIT_AUTOMATIC_INDEX) |
| 182 {/* zName: */ "automatic_index", |
| 183 -- |
| 184 2.11.0 |
| 185 |
OLD | NEW |