How to check BLOB size in a SQLite database
Solved Email & Outlook
MS
Michael Scofield
May 3, 2021
2 replies
6,180 views
Reviewed by moderators

An application's SQLite file has swollen to 4GB and I suspect the images it stores as BLOBs. I want per row sizes, per table totals and confirmation of where the bytes really live.

What are the queries and any traps in measuring BLOBs?

Accepted Answer
Verified by Eddie Thwan, Forum Moderator ยท Reviewed May 2021

SQLite makes this pleasantly queryable, length() on a BLOB returns bytes, and the traps are two, both avoidable once named.

Per row: SELECT id, length(image_data) AS bytes FROM photos ORDER BY bytes DESC LIMIT 20 surfaces the heavyweights immediately. Per table total: SELECT count(*), sum(length(image_data)), avg(length(image_data)), max(length(image_data)) FROM photos gives the column's full story in one row, and running the sum per BLOB column across your tables maps where the 4GB actually lives. Readable variant: printf('%.1f MB', sum(length(image_data))/1024.0/1024.0) spares the mental arithmetic.

Trap one, NULL handling: length(NULL) is NULL, not zero, so averages and sums quietly exclude empty rows, count them separately with SUM(CASE WHEN image_data IS NULL THEN 1 ELSE 0 END) when the emptiness itself is part of the story. Trap two, file size versus data size: a SQLite file never shrinks by itself, deleted BLOBs leave free pages the file keeps, so your sums can total 2GB inside a 4GB file. Compare data to file with PRAGMA page_count and PRAGMA freelist_count, a large freelist means the file is half air, reclaimed by running VACUUM, which rewrites the file compactly and frequently ends this exact investigation with a much smaller file and no data change at all.

For the browsing inclined, DB Browser for SQLite runs all of the above graphically and its Database Structure tab shows table sizes at a glance, handy for confirming the verdict the queries deliver.

Sums said 1.8GB of images inside the 4GB file and the freelist confirmed the rest was air from an old cleanup. VACUUM brought the file to 1.9GB in one pass. Both traps encountered, both named in advance, satisfying thread.