SQLite入门与分析(八)---存储模型(2)
3、页面结构(page structure)
数据库文件分成固定大小的页面。SQLite通过B+tree模型来管理所有的页面。页面(page)分三种类型:要么是tree page,或者是overflow page,或者是free page。
3.1、Tree page structure
每个tree page分成许多单元(cell),一个单元包含一个(或部分)payload。Cell是tree page进行分配或回收的基本单位。
一个tree page分成四个部分:
(1)The page header
(2)The cell content area
(3)The cell pointer array
(4)Unallocated space
Cell 指针数组与cell content相向增长。一个page header仅包含用来管理页面的信息,它通常位于页面的开始处(但是对于数据库文件的第一个页面,它开始第100个字节处,前100个字节包含文件头信息(file header))。
Structure of tree page header
Offset |
Size |
Description |
0 |
1 |
Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf |
1 |
2 |
Byte offset to the first free block |
3 |
2 |
Number of cells on this page |
5 |
2 |
First byte of the cell content area |
7 |
1 |
Number of fragmented free bytes |
8 |
4 |
Right child (the Ptr(n) value). Omitted on leaves. |
Flag定义页面的格式:如果leaf位被设置,则该页面是一个叶子节点,没有孩子;如果zerodata位被设置,则该页面只有关键字,而没有数据;如果intkey位设置,则关键字是整型;如果leafdata位设置,则tree只存储数据在叶子节点。另外,对于内部页面(internal page),header在第8个字节处包含指向最右边子节点的指针。
Cell位于页面的高端,而cell 指针数组位于页面的page header之后,cell指针数组包含0个或者多个的指针。每个指针占2个字节,表示在cell content区域的cell距页面开始处的偏移。页面Cell单元的数量位于偏移3处。
由于随机的插入和删除单元,将会导致一个页面上Cell和空闲区域互相交错。Cell内容区域(cell content area)中没有使用的空间收集起来形成一个空闲块链表,这些空闲块按照它们地址的升序排列。页面头1偏移处的2个字节指向空闲块链表的头。每一个空闲块至少4个字节,每个空闲块的开始4个字节存储控制信息:头2个字节指向下一个空闲块(0意味着没有下一个空闲块了),剩余的2个字节为该空闲块的大小。由于空闲块至少为4个字节大小,所以单元内容空间中的3个字节或更小的空间(叫做fragment)不能存在于空闲块列表中。所有碎片(fragment)的总的字节数将记录在页面头偏移为7的位置(所以太碎片最多为255个字节,在它达到最大值之前,页面会被整理)。单元内容区域的第一个字节记录在页面头偏移为5的地方。这个值为单元内容区域和未使用区域的分界线。
3.2、单元格式(Structure of a cell)
单元是变长的字节串。一个单元存储一个负载(payload),它的结构如下:
Structure of a cell |
|
Size |
Description |
4 |
Page number of the left child. Omitted if leaf flag bit is set. |
var(1–9) |
Number of bytes of data. Omitted if the zerodata flag bit is set. |
var(1–9) |
Number of bytes of key. Or the key itself if intkey flag bit is set. |
* |
Payload |
4 |
First page of the overflow chain. Omitted if no overflow. |
对于内部页面,每个单元包含4个字节的左孩子页面指针;对于叶子页面,单元不需要孩子指针。接下来是数据的字节数,和关键字的长度,下图描述了单元格式:(a)一个单元的格式 (b)负载的结构。
3.3、溢出页面
小的元组能够存储在一个页面中,但是一个大的元组可能要扩展到溢出页面,一个单元的溢出页面形成一个单独的链表。每一个溢出页面(除了最后一个页面)全部填充数据(除了最开始处的4个字节),开始处的4个字节存储下一个溢出页面的页面号。最后一个页面甚至可以只有一个字节的数据,但是一个溢出页面绝不会存储两个单元的数据。
溢出页面的格式:
3.4、实例分析
数据库为test.db,其中有一个表和索引如下:
CREATE TABLE episodes( id integer primary key,name text, cid int);
CREATE INDEX name_idx on episodes(name);
3.4.1、叶子页面格式分析:
Episodes表的根页面为第2个页面(此时episodes表只上一个页面),表中的数据如下:
sqlite> select * from episodes; 1|Cinnamon Babka2| 2|Mackinaw Peaches|1 3|Mackinaw Peaches|1 4|cat|1 5|cat|1 6|cat|1 7|cat|1 8|cat|1 9|cat|1 10|cat|1 11|cat|1 12|cat|1 13|cat2|40 14|hustcat|5 15|gloriazzz|41 16|eustcat|5 17|xloriazzz|41 |
下面为2号页面页面头(开始的8个字节):
Offset |
Size |
值 及含义 |
0 |
1 |
0x0D: 1: intkey, 2: zerodata, 4: leafdata, 8: leaf |
1 |
2 |
0x0000:第一个空闲块的偏移为0 |
3 |
2 |
0x0011:页面的单元数为17 |
5 |
2 |
0x031C:单元内容区的第一个字节的偏移(距页面起始位置) |
7 |
1 |
0x00:碎片字节数 |
8 |
4 |
Right child (the Ptr(n) value). Omitted on leaves. |
来看第2个页面的数据(0x400——0x7ff):
页面头之后为cell指针数组,第一个cell的相对页面起始位置偏移为0x03EB,即文件的0x07EB。该单元的数据为:
0x13:数据的字节数,19个字节,即04 00 2B … 61 32。
0x01:关键字的字节数,对于整型,则为关键字本身,即1。
0x04:从该字节开始为payload,即记录。0x04为记录头的大小。
0x00:NULL,id字段的值,由于关键字保存在key size中,这里为NULL
0x2B:name字段值的长度,为字符串,长度为(43-13)/2=15。
0x00:NULL,第一条记录cid的值。
(注:共有3个页面,由于篇幅所限,这里就不贴上来了)
SQLite入门与分析(八)---存储模型(2)的更多相关文章
- SQLite入门与分析(八)---存储模型(1)
写在前面:SQLite作为嵌入式数据库,通常针对的应用的数据量相对于通常DBMS的数据量是较小的.所以它的存储模型设计得非常简单,总的来说,SQLite把一个数据文件分成若干大小相等的页面,然后以B树 ...
- SQLite入门与分析(八)---存储模型(3)
写在前面:接上一节,本节主要讨论索引页面格式,以及索引与查询优化的关系. (1)索引页面格式sqlite> select * from sqlite_master;table|episodes| ...
- SQLite入门与分析(二)---设计与概念(续)
SQLite入门与分析(二)---设计与概念(续) 写在前面:本节讨论事务,事务是DBMS最核心的技术之一.在计算机科学史上,有三位科学家因在数据库领域的成就而获ACM图灵奖,而其中之一Jim G ...
- SQLite入门与分析(二)---设计与概念
写在前面:谢谢各位的关注,没想到会有这么多人关注.高兴的同时,也感到压力,因为我接触SQLite也就几天,也没在实际开发中用过,只是最近项目的需求才来研究它,所以我很担心自己的文章是否会有错误,误导别 ...
- SQLite入门与分析(四)---Page Cache之事务处理(1)
写在前面:从本章开始,将对SQLite的每个模块进行讨论.讨论的顺序按照我阅读SQLite的顺序来进行,由于项目的需要,以及时间关系,不能给出一个完整的计划,但是我会先讨论我认为比较重要的内容.本节讨 ...
- SQLite入门与分析(三)---内核概述(2)
写在前面:本节是前一节内容的后续部分,这两节都是从全局的角度SQLite内核各个模块的设计和功能.只有从全局上把握SQLite,才会更容易的理解SQLite的实现.SQLite采用了层次化,模块化的设 ...
- SQLite入门与分析(四)---Page Cache之事务处理(2)
写在前面:个人认为pager层是SQLite实现最为核心的模块,它具有四大功能:I/O,页面缓存,并发控制和日志恢复.而这些功能不仅是上层Btree的基础,而且对系统的性能和健壮性有关至关重要的影响. ...
- SQLite入门与分析(三)---内核概述(1)
写在前面:从本章开始,我们开始进入SQLite的内核.为了能更好的理解SQLite,我先从总的结构上讨论一下内核,从全局把握SQLite很重要.SQLite的内核实现不是很难,但是也不是很简单.总的来 ...
- SQLite入门与分析(七)---浅谈SQLite的虚拟机
写在前面:虚拟机技术在现在是一个非常热的技术,它的历史也很悠久.最早的虚拟机可追溯到IBM的VM/370,到上个世纪90年代,在计算机程序设计语言领域又出现一件革命性的事情——Java语言的出现,它与 ...
随机推荐
- git subtree
语法:git subtree split -P <被裁减的目录> -b <分支> git subtree split -P SDK/CustomUI(需要裁减的) -b Cus ...
- SQL 树结构统计数据
create table #Tmp( ID int IDENTITY (1,1) not null, name varchar(50), sl int); DECLARE @ID VARCHAR(36 ...
- SQL SERVER 与ACCESS、EXCEL的数据导入导出转换
* 说明:复制表(只复制结构,源表名:a 新表名:b) select * into b from a where 1<>1 * 说明:拷贝表(拷贝数据,源表名:a 目标表名:b) ...
- ###《Effective STL》--Chapter2
点击查看Evernote原文. #@author: gr #@date: 2014-09-15 #@email: forgerui@gmail.com Chapter2 vector和string T ...
- javaee学习-新建servlet 直接返回html
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletExcepti ...
- (CodeForces 510C) Fox And Names 拓扑排序
题目链接:http://codeforces.com/problemset/problem/510/C Fox Ciel is going to publish a paper on FOCS (Fo ...
- Entity Framework 学习笔记(2)
上期回顾:Entity Framework 学习笔记(1) Entity Framework最主要的东西,就是自己创建的.继承于DbContext的类: /// <summary> /// ...
- html常用单词和各种少见标签
常用单词: 空格 align="left"valign="top"align="center"valign="middle&qu ...
- ubuntu系统根目录下各个目录用途说明
1./ 根目录 --------- 所有目录挂在其下 2./boot --------- 存放Ubuntu内核和系统启动文件.系统启动时这些文件先被装载. 3./etc ---- ...
- Apache虚拟主机设置
Apache支持两种虚拟主机,一种是基于IP地址的,一种是基于域名的. 基于IP地址的虚拟机现在使用的很少,它需要一台服务器需要拥有多个IP地址.基于域名的虚拟主机要求服务器有一个IP地址就可以了,只 ...