SQLite数据库文件格式逐字节详解

sqlite用B+树的形式组织数据库中的数据。B+树有内部节点和叶子节点两种节点,对应的,数据库文件也有内部节点页和叶子节点页。
数据库中存储着两种数据,一种是表中的数据的集合(这些数据构成了一个表),一种是所有表的根节点集合(所有的表的根节点构成了master_catalog)。这两种数据都是通过B+树组织起来的,数据库文件中4KB大小的一个部分构成B+树的一页。

执行命令:”create table t1(a char, b char)” 和 “insert into t1 values(‘t’,’t’)” ,可以得到如下的数据库文件。文件大小是8KB,即2页,每页4KB。第一页是master_catalog,是叶子节点页,存储了所有的表的根节点,第二页也是叶子节点页,存储了表中具体的数据。我截取了有数据的部分,接下来我将逐个字节介绍sqlite的数据库文件格式。

Alt text
Alt text
Alt text
Alt text

数据库文件的第一页很特殊,它会包含一个100bytes大小的文件头。在本例中0x00~0x63是文件头。下面介绍文件头的格式:

0x00~0x0f: 字符串“SQLite format 3”
0x10~0x11: 页大小
0x12: 文件写格式 (1 for legacy; 2 for WAL)
0x13: 文件读格式
0x14: 每页底部保留bytes数(默认是0)
0x15: 内部节点页的最大嵌入负载(嵌入负载是个百分数,0~255代表0%到100%),这个值是用来限制最大的单个record的,如果最大嵌入负载是25%,那么单条record就不能超过1/4页,超过的部分会转移到溢出页
0x16: 内部节点页的最小嵌入负载
0x17: 叶子节点页的最小嵌入负载,叶子节点页的最大负载永远是100%,所以只给出叶子节点页的最小负载限制
0x18~0x1b: 文件被修改的次数,本例中该值是2,创建table和插入数据共修改了两次文件
0x1c~0x1f: 保留字节
0x20~0x23: 自由页链表头
0x24~0x27: 自由页页数
0x28~0x63: 15个4bytes的元数据

0x28~0x2b: schema cookies
0x2c~0x2f: schema格式
0x30~0x33: 默认页缓存大小
0x34~0x37: 在自动清空模式或者增量清空模式下,这个值是数据库文件中最大的B树根节点页。在其他模式下,这个值是0.
0x38~0x3b: 文本编码格式。A value of 1 means UTF-8. A value of 2 means UTF-16le. A value of 3 means UTF-16be.
0x3c~0x3f: 用户版本号。
0x40~0x43: 非零表示增量清空模式。零表示其他模式。
0x44~0x47: 应用程序号,用于表明sqlite属于特定的应用程序。
0x44~0x5b: 保留字节。
0x5c~0x5f: 最近修改数据库文件的sqlite库版本。
0x60~0x63: 保留字节。

接下来是正常的b+树节点页的页头。在本例中,第1页(master catalog)存储了所有的表,由于master catalog也是通过b+树组织的,而本例中只有一个表,第1页没有占满,所以第1页是master catalog所代表的b+树的叶子节点,也是master catalog所代表的b+树的唯一节点。

0x64: b树节点页类型。0x0d表示表的b+树的叶子节点页。
0x65~0x66: 第一个自由块的位置,自由块通过链表链接起来。自由块通常是由于cell的删除或更新产生的,自由块缩小到一定程度就成为了碎片,sqlite会按照一定的逻辑判断碎片数量并进行碎片整理。
0x67~0x68: 本页中cell的数量。本例中是1,这个cell存储了表t1。
0x69~0x6a: 第一个cell的偏移量。本例中是0xfd0 + 0。
0x6b: 碎片空间总大小。接下来的4bytes应该是最右孩子节点。但是这是叶子节点页,没有孩子,所以这4bytes省略了。
0x6c~0x6d: 指出cell的偏移量。具体参考官方文档中cell和cell pointer的存储方式。

接下来就是cell的格式了,存储位置为0xfd0~0xfff。cell的开头4bytes是左孩子的页号,但是本例中这一页是叶子节点页,没有孩子节点,所以这4bytes省略了。

0xfd0: 用变长度方式存储的数据大小,本例中是46,即从0xfd2到0xfff共46bytes数据。关于变长度方式存储,参见我的另一篇文章 SQLite 变长度整型(varint)编码解码方法
0xfd1: 键值大小,如果键值是整型变量,那么这个值就是键值本身。本例中sqlite为表t1自动分配了一个键值01。
0xfd2: header size。本例中是06,即0xfd3到0xfd7都是数据类型。数据类型的具体定义见官方文档。
0xfd3: 17转化为十进制就是23,(23-13)/2 = 5,代表第一个数据是5个字节大小的text,即“table”。
0xfd4: 11转化为十进制就是17,(17-13)/2 = 2,即t1。
0xfd5: 同上。
0xfd6: 以二进制补码形式存储的整型数据所占的byte。对应0xfe1的02,02是1byte。
0xfd7: 49转化为十进制就是73,(73-13)/2 = 30,即0xfe2到0xfff,刚好30个bytes。

至此,第一页已经介绍完了。接下来进入第二页,相较于第一页存储表本身的信息,第二页存储了表t1中的数据。

0x1000: b树节点页类型。0x0d表示表的b+树的叶子节点页。
0x1001~0x1002: 第一个自由块的位置。
0x1003~0x1004: 本页中cell的数量。本例中是1,这个cell存储了数据“tt”。
0x1005~0x1006: 第一个cell的偏移量。本例中是0xff9+1000。
0x1007: 碎片空间总大小。接下来的4bytes应该是最右孩子节点。但是这是叶子节点页,没有孩子,所以这4bytes省略了。
0x1008~0x1009: 指出cell的位置,即下面0x1ff9处的cell。
0x1ff9: 表示cell header有5个元素,即05 01 03 0f 0f。
0x1ff9~0x1ffd: 01是键值大小,如果键值是整型变量,那么这个值就是键值本身。本例中sqlite为数据“tt”自动分配了一个键值01。
0x1ffb: 03是header size,即接下来的0f 0f都表示数据类型。
0x1ffc~0x1ffd: 0f转化为十进制就是15,(15-13)/2 = 1,表示一个字节的text类型。
0x1ffe~0x1fff: 以ascii码形式保存的数据本身,即’t’。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLite是一种轻量级的嵌入式数据库管理系统,它不需要独立的服务器进程,将数据库引擎与应用程序打包在一起,作为一个完整的可执行文件。 要编辑SQLite数据库文件,首先需要安装SQLite的相关软件。常用的安装方式有使用命令行工具或者图形界面工具,例如使用命令行工具可以通过在终端输入"sqlite3"命令来进入SQLite的交互界面。 在数据库编辑过程中,我们可以执行各种SQL语句来修改、删除、添加数据库中的表和数据。通过SQLite的交互界面,我们可以使用诸如CREATE、SELECT、INSERT、UPDATE和DELETE等SQL语句来操作数据库。 例如,要创建一个名为"student"的表,可以使用以下SQL语句: ``` CREATE TABLE student ( id INTEGER PRIMARY KEY, name TEXT, age INTEGER ); ``` 要往表中添加数据,可以使用以下SQL语句: ``` INSERT INTO student (id, name, age) VALUES (1, 'John', 20); ``` 要查询表中的数据,可以使用以下SQL语句: ``` SELECT * FROM student; ``` 可以使用UPDATE语句修改表中已有的数据,使用DELETE语句删除表中的数据。 在编辑SQLite数据库文件时,需要注意对数据的正确操作,以免造成数据丢失或者数据库损坏。为了保证数据的安全性,最好在编辑数据库之前先备份原始的数据库文件。 总之,SQLite数据库编辑文件可以通过安装SQLite相关软件,在交互界面中使用各种SQL语句来操作数据库表和数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值