SQLite Forum

Setting non-binary columns to null in a table with a binary column populated with data creates free space and a larger file
Login
This has to do with the way Sqlite stores rows and also (intentionally?) disregarding the design rules regarding BLOB fields.

A row in the Sqlite format is stored as a "manifest" (this is a list of the types of the data stored in the row) and the "payload" (this is the actual data stored in the fields).

To access the value of a field, Sqlite has to parse the manifest to find the data types and skip the appropriate number of bytes in the payload to locate the values. Therefore it is recommended to put BLOBs last in the field list, so that the values of the other fields may be read without accessing the overflow area.

The original record in your example has the following representation:

Manifest:
.) header length
.) BLOB size X
.) INTEGER 1
.) TEXT 5

Payload:
x bytes BLOB
(nothing)
"MyKey"

After your updates, the record looks like:

Manifest:
.) header length
.) BLOB size x
.) NULL
.) NULL

Payload:
x bytes BLOB
(nothing)
(nothing)

Note that some values don't get stored in the Payload, specifically NULL, 0 and 1 are represented directly in the manifest. Setting some fields to NULL makes the representation shorter. And because your BLOB field is at the beginning of the field list, the overflow area has to be acessed and updated to reflect that.