Sqlite pager和B-tree的运行机制

Posted 单片机菜鸟哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sqlite pager和B-tree的运行机制相关的知识,希望对你有一定的参考价值。

官方文档:https://www.sqlite.org/index.html

1、Sqlite 嵌入式设备下的数据库

官方文档:

百度百科:

SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。

嵌入式设备本身内存空间小,这一点与sqlite不谋而合。

2、B-Tree和B+Tree

一般我们说B树,就是B-Tree(别说B减树)。
而B+Tree倒是叫做B加树。

2.1 B树

2.1.1 特点

  • B树每个节点都存储数据,所有节点组成这棵树,并且叶子节点指针为null;
  • B树中叶节点包含的关键字和其他节点包含的关键字是不重复的。

2.1.2 优点

  • B树的每一个节点都包含key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速。(可能访问一下就能得到我要的节点数据)

2.2 B+树

2.2.1 特点

  • B+树只有叶子节点存储数据(B+数中有两个头指针:一个指向根节点,另一个指向关键字最小的叶节点),叶子节点包含了这棵树的所有数据,所有的叶子结点使用链表相连,便于区间查找和遍历所有非叶节点起到索引作用
  • B+树的索引项只包含对应子树的最大关键字和指向该子树的指针,不含有该关键字对应记录的存储地址
  • B+树中查找,无论查找是否成功,每次都是一条从根节点到叶节点的路径。

2.2.2 优点

  • 所有的叶子结点使用链表相连,便于区间查找和遍历。B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。

  • b+树的中间节点不保存数据,能容纳更多节点元素

2.3 B树和B+树的共同特点

考虑磁盘IO的影响,它相对于内存来说是很慢的。数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘页(对应索引树的节点)。所以我们要减少IO次数,对于树来说,IO次数就是树的高度,而“矮胖”就是b树的特征之一,m的大小取决于磁盘页的大小。

3、Sqlite结构

在看一些网络帖子的时候,很多文章说 Sqlite中组织管理数据库文件存储的机制为B-树。(这句话不够严谨)。

严格意义上来说:

在Sqlite中使用了B-树和B+树。数据记录存储使用B-树,表索引使用B+树。这里可以叫做文件存储机制和索引机制。

不管是索引还是数据记录存储,最终都会涉及到持久化数据存储,也就是存储在磁盘中。

3.1 数据库文件格式 —— Pager

Sqlite中有一个概念叫做页面(Pager)。一个数据库文件被连续分割为n个页面,并给了一个页面号。

一个数据库由多个B树(统称B-、B+)组成 —— 每张表以及每个索引各对应一个B树(表使用B+树,索引使用B-树,这里需要涉及到B树优点)。
数据库中每张表或者索引都以根页面作为第一页。所有索引和表的根页面都存储在sqlite_master 中。

包括:

  • Root Page:根页面
  • Internal Page:内部页面
  • Leaf Page:叶子页面

3.2 B-Tree 记录

  • B-Tree中的页由一系列B-tree记录组成,这些记录叫做有效负载。一个B-tree记录仅仅由两个域组成:键值域(Key)和数据域(Data)。键值域是每个数据库表中所包含的RowId值或者主键值。用来保持记录有序并且方便记录查询;
  • 在B-Tree中,数据域可以包含任意类型的内容。数据库记录信息存储在数据域中。

3.3 B+Tree

  • 表使用B+Tree定义在内部页面(Internal Page),不包含表数据(数据库记录)。

  • B+tree的根页面(Root Page)和内部节点页(Internal Page)都用于搜索导航。这些页中的数据域均指向下一层页,这些页只是包含键值。

  • 在叶子页面(Leaf Page)。记录和页按照键值序排列,以便B-tree游标能够遍历记录(水平遍历)。是O(1)时间复杂度遍历记录成为可能。

以上是关于Sqlite pager和B-tree的运行机制的主要内容,如果未能解决你的问题,请参考以下文章

SQLite剖析之锁和并发控制

SQLite3的锁机制和并发控制详解

SQLite:仅从其字节识别页面类型?

数据库写入过程

片段无法加载到 View_pager tabLayout [重复]

Sqlite代写SQL执行语句代写