A database that uses auto-vacuum or incremental vacuum gives free pages back by moving pages from the end of the file into the gaps and then truncating it. To move a page, SQLite must change whatever points to it, so it keeps a map of every page’s parent: the pointer-map pages. They are present exactly when header offset 52 is not zero. Auto-vacuum came with SQLite 3.1.0 (2005).
Where they are
Each pointer-map page holds J = U ÷ 5 entries, rounded down, where U is the usable size. The first pointer map is page 2 and describes the J pages after it, pages 3 to J + 2. The next pointer map is page J + 3, describing pages J + 4 to 2J + 3, and so on: pointer maps sit at pages 2 + k × (J + 1) for k = 0, 1, 2 …. If one would fall on the lock-byte page, it moves to the next page.
| Usable size | Entries per page (J) | Pointer maps at pages |
|---|---|---|
| 1,024 | 204 | 2, 207, 412 … |
| 4,096 | 819 | 2, 822, 1,642 … |
Since the places follow from the page size alone, a reader can find every pointer map without reading anything else.
Entries
A pointer-map page is an array of 5-byte entries, one for each page that follows it, in order: entry i describes page B + 1 + i, where B is the pointer map’s own page number. The bytes after the last whole entry are unused.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 1 | u8 | Type | What the page is: see Entry types. |
| 1 | 4 | u32 | Parent page | The page that points to it, or 0. |
Entry types
| Type | The page is | Parent page |
|---|---|---|
1 | the root page of a b-tree | 0 |
2 | a freelist page | 0 |
3 | the first page of an overflow chain | the b-tree page holding the cell |
4 | a later page of an overflow chain | the previous page of the chain |
5 | a b-tree page that is not a root | its parent b-tree page |
In these databases every root page comes before every other b-tree page, overflow page and freelist page. Vacuuming therefore never has to move a root page, whose number is stored in the schema table.