Small. Fast. Reliable.
Choose any three.

About Sitemap Documentation Download License News Support |

## The DBSTAT Virtual Table

The dbstat virtual table is available on all database connections when SQLite is built using the SQLITE_ENABLE_DBSTAT_VTAB compile-time option. The dbstat virtual table provides low-level information about btree and overflow pages in the main database file. The dbstat virtual table itself can exist in any database (TEMP is recommended) but it always provides information about only the main database.

The recommanded way to create an instance of the dbstat virtual table is as follows:

>     CREATE VIRTUAL TABLE temp.stat USING dbstat;

Note the "temp." qualifier before the virtual table name ("stat"). This qualifier causes the virtual table to be temporary - to only exist for the duration of the current database connection. This is the recommended approach.

The schema for the dbstat virtual table is this:

>     CREATE TABLE dbstat(
>       name       STRING,     -- Name of table or index
>       path       INTEGER,    -- Path to page from root
>       pageno     INTEGER,    -- Page number
>       pagetype   STRING,     -- 'internal', 'leaf' or 'overflow'
>       ncell      INTEGER,    -- Cells on page (0 for overflow)
>       payload    INTEGER,    -- Bytes of payload on this page
>       unused     INTEGER,    -- Bytes of unused space on this page
>       mx_payload INTEGER,    -- Largest payload size of all cells on this page
>       pgoffset   INTEGER,    -- Offset of page in file
>       pgsize     INTEGER     -- Size of the page
>     );

There is a single row of the dbstat table for each page in the main database file. Freelist pages, the lock page, and pointer-map pages of the database file do not appear in the dbstat virtual table.

### The "path" column of the dbstat virtual table

The "path" column describes the path taken from the root node of the btree structure to each page. The "path" of the root node itself is '/'. The "path" for the left-most child page of the root of a btree page is '/000/'. (Btrees store content ordered from left to right so the pages to the left have smaller keys than the pages to the right.) The next to left-most child of the root page is '/001', and so on, each sibling page identified by a 3-digit hex value. The children of the 451st left-most sibling have paths such as '/1c2/000/, '/1c2/001/' etc. Overflow pages are specified by appending a '+' character and a six-digit hexadecimal value to the path to the cell they are linked from. For example, the three overflow pages in a chain linked from the left-most cell of the 450th child of the root page are identified by the paths:

>     '/1c2/000+000000'         // First page in overflow chain
>     '/1c2/000+000001'         // Second page in overflow chain
>     '/1c2/000+000002'         // Third page in overflow chain

If the paths are sorted using the BINARY collation sequence, then the overflow pages associated with a cell will appear earlier in the sort-order than its child page:

>     '/1c2/000/'               // Left-most child of 451st child of root

### Example uses of the dbstat virtual table

To find the total number of pages used to store table "xyz", use:

>     CREATE VIRTUAL TABLE IF NOT EXISTS temp.stat USING dbstat;
>     SELECT count(*) FROM stat WHERE name='xyz';

To see how efficiently the content of a table is stored on disk, compute the amount of space used to hold actual content divided by the total amount of disk space used. The closer this number is to 100%, the more efficient the packing.

>     CREATE VIRTUAL TABLE IF NOT EXISTS temp.stat USING dbstat;
>     SELECT sum(pgsize-unused)/sum(pgsize) FROM stat WHERE name='xyz';

To find the average fan-out for a table, run:

>     CREATE VIRTUAL TABLE IF NOT EXISTS temp.stat USING dbstat;
>     SELECT avg(ncell) FROM stat WHERE name='xyz' AND pagetype='internal';

Modern filesystems operate faster when disk accesses are sequential. Hence, SQLite will run faster if the content of the database file is on sequential pages. To find out what fraction of the pages in a database are sequential (and thus obtain a measurement that might be useful in determining when to VACUUM), run a query like the following:

>     CREATE VIRTUAL TABLE IF NOT EXISTS temp.stat USING dbstat;
>     CREATE TEMP TABLE s(rowid INTEGER PRIMARY KEY, pageno INT);
>     INSERT INTO s(pageno) SELECT pageno FROM stat ORDER BY path;
>     SELECT sum(s1.pageno+1==s2.pageno)*1.0/count(*)
>       FROM s AS s1, s AS s2
>      WHERE s1.rowid+1=s2.rowid;
>     DROP TABLE s;