B-Tree数据存储

来源:互联网 发布:pp助手 mac 备份app 编辑:程序博客网 时间:2024/05/09 17:10

SQLITE数据存储

1. B-Tree的优势

  在SQLite中数据库、表、索引都是通过B-Tree和B+Tree的形式进行存储的。如果采用传统的二叉树查找树、红黑树的查找深度一般为log2(N)(其中N表示的是整个树的关键字的数目),在数据库中如果存储的资源过多,就会导致查找一个数据过程中出现较多的磁盘I/O操作,而过多的磁盘操作就会导致整个查找的效率较低,而基于二叉树的一种思想,出现一种“多叉树”的思想,如果在原来的基础上,每个结点中包含的孩子不止两个,那整个树的深度就会降低,在查找过程中所需进行的磁盘I/O操作相教于原先的二叉树就会出现很大的降低,而这种“多叉树”就是B-Tree和B+Tree。
  假设有一个M阶的B-Tree(或B+ Tree其中B+-Tree仅仅是B-Tree的一个改进),其中关键字的数据为N,那么整个B树的深度为log(M/2)(N+12),当整个数据库中资源存储量较大,如果B-Tree阶数M较大,那么整个B-Tree的深度就会大大减小,查找的效率就会大大提高。

2. B-Tree在SQLite中应用

2-1 SQLite中存储形式


这里写图片描述
图1 B-Tree存储形式

表 (Table) —–  B+-Tree 在整个B+ Tree中分为内部节点(Internal Node)和叶子结点(Leaf Node),但是内部节点只是起到一个索引的作用,所有的关键字全部存在叶子结点中
索引(Index) —–  B-Tree 在整个B-Tree中不论叶子结点和内部节点中既包括关键字也包括孩子节点指针,但是在SQLite中B-Tree是一个simply “B-Tree”,索引B-Tree中只存储指针,忽略了数据。SQLite官方文档描述如下:

The algorithm that Knuth calls simply “B-Tree” stores both the key and the data together in both leaves and in interior pages. In the SQLite implementation, the original B-Tree algorithm stores keys only, omitting the data entirely, and is called an “index b-tree”.

  在数据文件中存储的最小单元为一个单元(cell),其中每一个单元包括一个孩子指针和一个关键字,这种结构组成了数据库文件中一个最小结构。
  
2-2 SQLite中数据库文件格式
  整个数据库文件中由许多“页”组成,每一个数据库文件中每页的大小和整个数据库文件最多可以由多少页组成,可以查看SQlite源码中SQliteInt.h这一章节,也可以查看SQLite官方文件链接,这里主要描述整个文件的整体存储结构和是怎样通过B-Tree的形式进行存储,具体的文件描述不再描述。
  2-2-1 SQLite文件整体存储结构

这里写图片描述
  图2 页面存储结构
  这里写图片描述
  图3 单元存储结构

  2-2-2 文件分析
  在2-2-1中只是将整个文件的存储形式通过表格的形式给出,在本小节中通过具体的数据库文件的形式给出分析。在sqlite3中建立一个新的数据库文件rxd.db,并且在其中建立一个表foos,表格的具体形式如下表格所示(下图仅仅是一个表格格式:

id type_id name 1 1 james 2 1 wade 3 1 kobe
@SQL代码sqlite>create table rxd(   ...>id int primary key,   ...>type_id int,   ...>name text);

然后通过Insert into foods values()向表格中插入100条表项记录,插入完成后的结果如图4所示(截图中只是部分表项):

这里写图片描述
图4 foods表格

下面结合上面页面格式和单元格式对整个数据库文件进行分析,在数据库文件中涉及到的碎片、自由块、空闲页这里不进行分析(还未完全理解,这部分后序会继续添加到这个文档中),另外索引数据库文件由于前面未进行整理。
  整个数据库文件总共大小为6K,在这里我们设置的每一页的大小为1K,因此整个B+-Tree总共由6个页面,即6个结点,其中第一页中包含整个数据库的文件头和一张系统的sqlite_master表,具体这张表中包含内容如下图5所示:

这里写图片描述
图5 第一页文件内容

其中包括我们的建立的表格foods的信息,第二页页头信息如下:
这里写图片描述

项目 说明 05 表内部节点(页) 00000006 最右孩子页面(孩子指针)表明最右孩子是第6页

这里写图片描述
除去文件头后,剩下的四个字节0x03FB、0x3F6是单元指针数组中保存的两个单元指针。
0x400 + 0x3FB —–>第一个单元 这里写图片描述 表明左指针指向第4页,行号为2E。
0x400 + 0x3F6 —–>第二个单元 这里写图片描述表明左指针指向第5页,行号为59。
通过上面的分析整个数据库文件整个数据存储形式框架如下图6所示:

这里写图片描述
图6foods存储形式

  上面只是就就整个rxd.db的整体存储结构进行的总结,但是其中许多存储的细节还没有叙述清楚,在后面阅读源码的过程中继续补充。
  
2-3 文件格式与B-Tree源代码结合分析
  这一块内容应该是整个B-Tree在SQLite中应用的核心部分,目前自己通过分析B-TreeInt.h、B-Tree.h、B-Tree.c、pager.c等相关源码(其中B-Tree中大约有9000行代码,目前只阅读了4000行,依然还没有完全和整个文件存储形式结合起来),在接下来的这一周中自己做的主要工作就是尽量将这一块完成。

原创粉丝点击