SQLite剖析之存储模型

本文详细剖析了SQLite的存储模型,介绍了其文件格式,包括页面结构、页面类型、文件头和元数据。SQLite将数据库分为固定大小的页面,通过B树组织数据,支持叶子页面、内部页面、溢出页面和空闲页面。文件头包含关键信息,如页面大小、文件格式和空闲页面链表。页面结构包括单元格和空闲空间管理。通过对实际数据库和索引页面的分析,展示了SQLite如何存储数据和实现排序。
摘要由CSDN通过智能技术生成

SQLite剖析之存储模型

前言

  SQLite作为嵌入式数据库,通常针对的应用的数据量相对于DBMS的数据量小。所以它的存储模型设计得非常简单,总的来说,SQLite把一个数据文件分成若干大小相等的页面,然后以B树的形式来组织这些页面。而对于大型的数据库管理系统,比如Oracle,或者DM ,存储模型要复杂得多。就拿Oracle来说吧,它对数据文件不仅从物理上进行分块,而且从逻辑上进行分段,盘区和页的一个层次划分DM也一样。不管怎么说,数据库文件要存储大量的数据,为了更好管理,查询和操作数据文件,DBMS不得不从物理上、逻辑上对数据文件的数据进行复杂的组织。

1.文件格式

1.1、数据库名称

  应用程序通过sqlite3_open(API)来打开数据库,该函数的一个参数为数据库文件的名称。SQLite内部命名为main数据库(除了临时数据库和内存数据库)。SQLite对每一个数据库都创建一个独立的文件。
  在SQLite内部,数据文件名不是数据库名。SQLite对应用程序的每一个连接都维护着一个单独的临时数据库(temp数据库),临时数据库存临时对象,例如表以及相应的索引。这些临时对象仅仅对同一个连接可见(对同一个线程、进程的其它连接是不可见的),SQLite存储临时数据库到一个单独的临时文件中,当应用程序关闭对main数据库的连接时,就删除临时文件。

1.2、数据库文件结构

  除了内存数据库,SQLite把一个数据库(main和temp)都存储到一个单独的文件。

1.2.1、页面(page)

  为了更好的管理和读/写数据库,SQLite把一个数据库(包括内存数据库)分成一个个固定大小的页面。页面大小的范围从512-32768(两者都包含),页面默认大小为1024个字节(1KB),实际上页面的上限由2个字节的有符号整数决定。整个数据库可以看成这些页面的数组,页面数组的下标为页面的编号(page number),page number从1开始,一直到2、147、483、647 (2^31– 1)。实际上,数组上界还受文件系统允许的最大文件大小决定。0号页面视为空页面(NULL page),物理上不存在,1号页面从文件的0偏移处开始,一个页面接着下一个页面。

  注意:一旦数据库创建,SQLite使用编译时确定的默认的页面大小。当然,在创建第一个表之前,可以通过pragma命令改变页面大小。SQLite把该值作为元数据的一部分存储在文件中。

1.2.2、页面类型

  页面(page)分四种类型:叶子页面(leaf),内部页面(internal),溢出页面(overflow)和空闲页面(free)。内部页面包含查询时的导航信息,叶子页面存储数据,例如元组。如果一个元组的数据太大,一个页面容纳不下,则一些数据存储在B树的页面中,余下的存储在溢出页面中。

1.2.3、文件头(file header)

  作为文件开始的1号页面比较特殊,它包括100个字节的文件头。当SQLite创建文件时先初始化文件头,文件头的格式如下: 

Structure of database file header

Offset

Size

Description

0

16

Header string  

16

2

Page size in bytes

18

1

File format write version  

19

1

File format read version

20

1

Bytes reserved at the end of each page

21

1

Max embedded payload fraction

22

1

Min embedded payload fraction

23

1

Min leaf payload fraction

24

4

File change counter

28

4

Reserved for future use

32

4

First freelist page

36

4

Number of freelist pages

40

60

15 4-byte meta values

  示例数据(100个字节):

53 51 4C 69 74 65 20 66 6F 72 6D 61 74 20 33 00 ; SQLite format 3.

04 00 01 01 00 40 20 20 00 00 00 11 00 00 00 00 ; .....@........

00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 01 ; ................

00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ; ................

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................

00 00 00 00

前16个字节-Header string(头字符串):"SQLite format 3."

0x04 00 :页面大小-Page size,即1024
0x01 01 :文件格式-File format(写、读各一字节),在当前的版本都为1。
0x00 : 保留空间-Reserved space,1个字节,SQLite在每个页面的末尾都会保留一定的空间,留作它用,默认为0。
0x40 20 20 :max embedded payload fraction(偏移21)的值限定了B树内节点(页面)中一个元组(记录,单元)最多能够使用的空间,255意味着100%,默认值为0x40,即64(25%),这保证了一个结点(页面)至少有4个单元。如果一个单元的负载(payload,即数据量)超过最大值,则溢出的数据保存到溢出的页面,一旦SQLite分配了一个溢出页面,它会尽可能多的移动数据到溢出页面;下限为min embedded payload fraction value(偏移为22),默认的值为32,即12.5% ;min leaf payload fraction的含义与min embedded payload fraction类似,只不过是它是针对B树的叶子结点,默认值为32,即12.5%,叶子结点最大的负载为通常是100%,这不用保存。
0x00 00 00 11 :文件修改计数-File change counter,通常被事务使用,它由事务增加其值。该值的主要目的是数据库改变时,pager避免对缓存进行刷盘。

空闲页面链表(Freelist):在文件头偏移32的4个字节记录着空闲页面链的第一个页面。
空闲页面的数量:偏移36处的4个字节为空闲页面的数量。

空闲页面链表的组织形式如下:

  空闲页面分为两种页面:trunk pages(主页面)和leaf  pages(叶子页面)。文件头的指针指向空闲链表的第一个trunk page,每个trunk page指向多个叶子页面。
  Trunk page的格式如下,从页面的起始处开始:
   (1)4个字节,指向下一个trunk page的页面号;
   (2)4个字节,该页面的叶子页面指针的数量;
   (3)指向叶子页面的页面号,每项4个字节。
  当一个页面不再使用时,SQLite把它加入空闲页面链表,并不从本地文件系统中释放掉。当添加新的数据到数据库时,SQLite就从空闲链表上取出空闲页面用来再存储数据。当空闲链表为空时,SQLite就通过本地文件系统增加新的页面,添加到数据库文件的末尾。
  注:可以通过vacuum命令删除空闲链表,该命令通过把数据库中数据拷贝到临时文件,然后在事务的保护下,用临时文件中的复本覆盖原数据库文件。

  元数据变量(Meta variables):从偏移为40开始,为15个4字节的元数据变量,这些元数据主要与B树和VM有关。如下:

 ** Meta values are as follows:

 **    meta[0]   Schema cookie. Changes with each schema change.

 **    meta[1]   File format of schema layer.

 **    meta[2]   Size of the page cache.

 **    meta[3]   Use freelist if 0. Autovacuum if greater than zero.

 **    meta[4]   Db text encoding. 1:UTF-8 2:UTF-16LE 3:UTF-16BE

 **    meta[5]   The user cookie. Used by the application.

 **    meta[6]  

 **    meta[7]

 **    meta[8]

 **    meta[9] 

1.2.4

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值