2010年10月9日 傅翠云 发表评论 阅读评论

Berkeley DB(以下简称BDB)支持四种访问方法,Btree,hash,queue,recno。BTree访问方法使用多叉BTree存储数据,hash访问方法使用可动态扩展的哈希表存储数据,queue访问方法支持顺序或逻辑记录数访问定长数据,recno访问方法支持顺序或逻辑记录数访问定长或者非定长数据,其中Btree应用最为广泛。本文将深入探讨BDB中Btree的结构以及影响Btree性能的各种配置和方法,旨在引导读者更好的理解和优化Btree的使用,转载请注明出处。

I. BDB中Btree结构
BDB中Btree存储数据库的元数据信息,索引及数据信息。元数据信息存储在元数据结点上,索引及数据本身等以不同的数据格式存储在相应的结点上。

如上图所示,Btree有五种类型的结点(页),元数据结点,中间结点,叶子结点,溢出结点和重复结点。他们分别以P_BTREEMETA,P_IBTREE,P_LBTREE,P_OVERFLOW和P_LDUP的类型存在。除了元数据结点以外,其他结点都以Btree页为基本格式存在:

typedef struct _db_page {
DB_LSN lsn; /* 00-07: 日志序列号. */
db_pgno_t pgno; /* 08-11: 当前页号*/
db_pgno_t prev_pgno; /* 12-15: 前一页. */
db_pgno_t next_pgno; /* 16-19: 后一页. */
db_indx_t entries; /* 20-21: 页里数据个数. */
db_indx_t hf_offset; /* 22-23: 空闲字节偏移量最高位. */
u_int8_t level; /* 24: Btree 树层. */
u_int8_t type; /* 25: 页类型. */
} PAGE;

Btree中每页至少含有上述26个字节的头部分,若有校验,其后紧跟校验码。此后则是数据部分,根据页类型不同,数据分布各有不同。

下面分别介绍这五种不同结点。
1. 元数据结点
元数据包含与该Btree数据库相关的特定信息,以BTMETA33(或者BTMETA)的结构存在,分为基本元信息DBMETA33(或者DBMETA)和Btree特定元信息。

Btree特定元信息包括Btree页最小key个数,根结点,加密,校验等等,基本元信息包括日志序列号,当前页号,版本号,页大小,页类型,最后一页页号,分区号等等。

Btree的元数据信息存储在同一页,以便操作过程中频繁被访问。Btree元数据结构占用空间512字节,因此Btree的页大小的下限是512字节。

2. 中间结点
Btree的中间结点存储着key的索引。在Btree页头以后,在index的位置依次存储页内每一条索引记录的偏移量,而索引记录本身从尾部开始存储。每一条索引记录结构如下:

typedef struct _binternal {
db_indx_t len; /* 00-01: key数据长度. */
u_int8_t type; /* 02: 页类型和删除标记. */
u_int8_t unused; /* 03: 未用空间. */
db_pgno_t pgno; /* 04-07: 指向页的页号. */
db_recno_t nrecs; /* 08-11: 子树个数. */
u_int8_t data[1]; /* key内容. */
} BINTERNAL;

一个中间结点包含PAGE中的头信息及众多BINTERNAL索引记录,其页结构如下:

其中上一页页号(prev pgno)为父亲结点的页号,下一页页号(next pgno)不维护。

Btree的中间结点的层数很大程度上影响了查询效率。BDB的Btree是平衡树,但通常情况下中间结点不会超过三层。假设Btree数据库页大小为4096字节,无校验,32位整型key,理想情况下,任何一个中间结点可索引(4096 – 26) / (12 + 4) = 254个key,则一层中间结点最多可索引254个key,两层中间结点最多可索引254 * 254 = 64516个key,三层中间结点可索引最多可索引(254 * 254) ^2 = 4162314256个key。当key较大时,用户可适度扩大页的大小,以增加每一个页索引的个数,减少 Btree树的层数。

3. 叶子结点
叶子结点存储key和data的内容。与中间结点类似,此类结点的页头后面分别存储着每对key和data的偏移量,且在页尾成对存储着key和data相应的数据记录。每一条数据记录结构如下:

typedef struct _bkeydata {
db_indx_t len; /* 00-01: key数据长度. */
u_int8_t type; /* 02: 页类型和删除标记. */
u_int8_t data[1]; /* key/data内容. */
} BKEYDATA;

一个叶子结点包含PAGE中的头信息及众多BKEYDATA数据记录,其页结构如下:

叶子结点的上一页页号记录上一个叶子结点的页号,下一页页号记录下一个叶子结点的页号。叶子结点之间是相互链接的,因此,遍历整个数据库仅需要依次访问下一页(或者上一页)叶子结点即可。

页中间的空闲区越小,该页的利用率越高。当一页的空闲区不足以插入一条新数据时,该页将被分裂,该页一半的数据将分配到新页中。频繁的分裂可能产生大量较低利用率的页,如果可优化插入的数据使其有序,可在一定程度上避免出现大量低利用率的页。

利用率低的页浪费较多空间,而且增加了访问这些页中数据所需要读的页的个数,从而影响访问效率。然而,空间利用率并不是越高越好,由于BDB是页级锁,若一个页的记录较多,其更新的并发性也相对较弱。因此,页的空间利用率并非总是越高越好,需要根据具体的应用场景做出合理的选择。

4. 溢出结点
当存储的索引或记录数据的大小超过约四分之一页时,该数据内容将依次存储在几个溢出结点中,并组成一个溢出链表。该条溢出数据将首个溢出结点的页号,数据长度等记录在其相应的中间结点或者叶子结点中。每一条溢出数据(key或者data)的结构如下:

typedef struct _boverflow {
db_indx_t unused1; /* 00-01: 未用填充空间. */
u_int8_t type; /* 02: 页类型和删除标记. */
u_int8_t unused2; /* 03: 未用填充空间. */
db_pgno_t pgno; /* 04-07: 页号. */
u_int32_t tlen; /* 08-11: 完整长度. */
} BOVERFLOW;

溢出链表中每一个结点的页头开始顺序存储溢出数据。任何一个溢出链表仅保存一个溢出数据,因此,每一个溢出链表最后一个溢出结点上的剩余空闲块将无法被下一个溢出数据复用。

当溢出数据普遍存在于各个记录时,亦可考虑将该类溢出数据存储在其他数据库(例如hash)中,在当前数据库中仅存储其引用。例如,每一个图片信息分为元数据和图片数据,元数据包括图片编号,图片名,作者,创作时间,图片数据则是图片本身。在BDB中,若将元数据和图片数据存储在同一条Btree记录中,由于图片数据较大,元数据和图片数据都将被存储在溢出结点中,每次访问图片元数据都需要访问一个叶子或中间结点,再找到其相应的溢出结点。此时,可在Btree数据库中存储图片的元数据,而在hash数据库中存储图片编号及图片本身。这样,当频繁访问图片元数据时,不需要每次读出溢出结点,从而提高访问性能。

5. 重复结点
当同一个key允许有多个不同的data时,即key可重复时,其相应的data将以BOVERFLOW的结构存储在当前叶子结点中,其中的页号为当前key的重复链表的第一个结点的页号。重复结点跟中间结点类似,不同的是,重复结点仅存储同一个key对应的各个data。

以上关于不同结点的结构均可在源代码中的dbinc/db_page.h中找到。

II. 使用工具查看Btree的统计信息和内容
1. db_stat
db_stat是BDB自带的工具,提供了BDB环境中数据库、事务、锁、缓存等统计信息,其相应的API是 DB->stat()或DB->stat_print()。

”db_stat -d”可查看某个具体数据库信息,Btree数据库的统计信息包括:

- Btree magic number: Btree幻数
- Btree version number: Btree版本号
- Byte order:字节顺序
- Flags: 配置
- Minimum keys per-page: 每页key的最少数目
- Underlying database page size:页大小
- Overflow key/data size: 溢出key/data字节数
- Number of levels in the tree: 树的层数
- Number of unique keys in the tree: 不重复的key的个数
- Number of data items in the tree:data的个数
- Number of tree internal pages: 中间结点的个数
- Number of bytes free in tree internal pages: 中间结点的空闲字节数
- Number of tree leaf pages:叶子结点的个数
- Number of bytes free in tree leaf pages:叶子结点中的空闲字节数
- Number of tree duplicate pages:重复结点的个数
- Number of bytes free in tree duplicate pages: 重复页的空闲字节数
- Number of tree overflow pages:溢出结点的个数
- Number of bytes free in tree overflow pages :溢出结点的空闲字节数
- Number of empty pages:空页的个数
- Number of pages on the free list:空闲列表中的页个数

根据上述统计信息,可获知Btree的key/data数目,不同结点的空间使用情况。可据此做适当的调优,例如调整页大小以获得更佳的空间利用率,压紧以释放空闲空间等等。

2. db_dump
db_ dump是BDB自带的工具,用于查看数据内容,其输出格式包括两部分:头部分和数据部分,头部分包括版本,格式,类型,设置,页大小等等。如下所示:

VERSION=3
format=bytevalue
type=Btree
duplicates=
db_pagesize=

HEADER=END

DATA=END

db_dump可直观地看到数据在BDB的存储内容,亦可结合db_load完成数据迁移工作。当数据库没有开启事务时,亦可辅助拯救出错页前的有效数据。

III. 配置Btree
以下配置Btree的方法都应在打开Btree前完成。
1. 设置页大小:DB->set_pagesize()
2. 设置缓存大小:DB->set_cachesize()
3. 设置Btree中key的比较函数:DB->set_bt_compare()
默认按照字典顺序大小,短字节排在长字节前。
4. 设置Btree中间结点的前缀比较函数:DB->set_bt_prefix()
保证key的唯一性的前提下,尽可能减少中间结点存储的key的字节数,当key有大量重复的字节时,可减小树的大小及提高查询性能。
5. 设置Btree压缩函数:DB->set_bt_compress()
默认压缩函数在所有key上执行前缀压缩,当压缩后的key与前一个相同时,则对data进行压缩。若要使用定制的压缩函数,则需要提供其相应的解压函数。
6. 设置允许重复或者有序重复:DB->set_flags()
设置DB_DUP允许同一个key有不同data,设置DB_DUPSORT类似DB_DUP,且这些data是有序的。
7. 设置重复比较函数:DB->set_dup_compare()
同一个key的不同data之间的比较函数。
8. 设置每页最小key数:DB->set_bt_minkey()
设置每页中至少有多少个key。
9. 设置记录数:DB->set_flags()中设置DB_RECNUM
除了key以外,允许使用记录数获取Btree里的记录。
10. 设置反向分裂:DB->set_flags()中设置DB_REVSPLITOFF
当数据库周期性地增大和缩小时,可关闭反向分裂,避免死锁,提高性能。

IV. 其他Btree常用方法
1. DB->compact()
压紧数据库并选择性地释放空闲链表上的页。可通过配置Btree填充率,释放页个数及时延,来控制压紧过程。另外,可对整个数据库进行压紧,亦可只释放空闲链表中已有的页空间。

2. DB->key_range()
DB->key_range()可查看当前key在数据库所有key中的大概位置,大于,小于或者等于该key的比例。

V. 参考文档

  • C API文档

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/263089/viewspace-684038/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/263089/viewspace-684038/

BDB的Btree结构以及影响Btree性能的各种配置和方法相关推荐

  1. 尤佳轩、何恺明等提出新型图表示法,新视角理解图结构如何影响预测性能

    选自arXiv 作者:尤佳轩.Jure Leskovec.何恺明.Saining Xie 机器之心编译 参与:小舟.杜伟 神经网络的图结构和预测性能之间有怎样的关系?近日,斯坦福尤佳轩.Jure Le ...

  2. mysql查询时,offset过大影响性能的原因与优化方法

    遇到的问题 我们大家都知道,mysql查询使用select命令,配合limit,offset参数可以读取指定范围的记录,但是offset过大影响查询性能的原因及优化方法,这次工作中因为要导出40W的数 ...

  3. MySQL进阶篇(02):索引体系划分,B-Tree结构说明

    本文源码:GitHub·点这里 || GitEE·点这里 一.索引简介 1.基本概念 首先要明确索引是什么:索引是一种数据结构,数据结构是计算机存储.组织数据的方式,是指相互之间存在一种或多种特定关系 ...

  4. Mysql 索引 总结 —— 概述 || 索引优势劣势|| 索引结构(索引是在MySQL的存储引擎层中实现的)|| BTREE 结构||B+TREE 结构||MySQL中的B+Tree||索引分类

    索引概述 MySQL官方对索引的定义为:索引(index)是帮助MySQL高效获取数据的数据结构(有序). 在数据之外,数据库系统还维护者满足特定查找算法的数据结构, 这些数据结构以某种方式引用(指向 ...

  5. ICML2020 | 神经网络的图结构如何影响其预测性能?

    作者 | 董靖鑫 审稿 | 程玉 今天给大家介绍的是来自斯坦福大学的Jure Leskovec课题组发表在ICML2020上的文章" Graph Structure of Neural Ne ...

  6. B-tree结构菜单的递归查询

    有层次结构的菜单树,后台库表结构通常会设计为B-tree结构, 就是菜单节点上有一个PID字段,记录自己的父节点号, 通过这种自关联的方式隐含树的层次结构,如: CREATE TABLE T_MENU ...

  7. case when影响性能吗_字段为NULL会影响查询性能吗?

    导读 假设这个用户中心系统是一个交友平台的一个子系统,现在产品想要提供一个按生日区间筛选用户的功能.那么,要实现这个功能,我们需要写这么一条SQL: SELECT 为了保证这条SQL的查询性能,我们会 ...

  8. 影响数据库性能的因素

    论坛上的数据库爱好者们,对于数据库底层的各种细节,内幕,等待事件,隐藏参数等津津乐道,对于调整好一条SQL语句使之在查询优化器/查询引擎下能高性能运转具有巨大的满足感成功感,仿佛自己掌握了天下最有价值 ...

  9. 对MySQL性能影响关系紧密的五大配置参数

    以下的文章主要是对MySQL性能影响关系紧密的五大配置参数的介绍,我前几天在相关网站看见对MySQL性能影响关系紧密的五大配置参数的资料,觉得挺好,就拿出来供大家分享,望你能有所收获. (一)连接 连 ...

最新文章

  1. 以太坊和EOS DApp数量上升
  2. CC2530之Flash笔记
  3. 失业日志:2009年10月12日星期一
  4. show index mysql_MySQL SHOW INDEX语法的实际应用
  5. 无法在web服务器上启动调试。调试失败,因为没有启用集成windows身份验证
  6. SUM OF SUB RECTANGLE AREAS(打表+oeis+c++大数类板子)
  7. CorelDRAWX4的VBA插件开发(二)怎么查看开发者PDF文档和VBA内的对象浏览器
  8. mouseenter、mouseleave、mouseover和mouseout的区别
  9. 微波遥感几个重要公式
  10. 扫外部二维码进入小程序,并且在小程序内获取二维码链接
  11. win7计算机自动关机设置在哪里设置方法,win7系统怎么设置每天自动关机|win7创建定时关机计划的方法...
  12. Niagara程序入门
  13. Redis6客户端工具——Jedis
  14. 在ubuntu20.04下搭建lamp环境并制作静态网页
  15. 数据库系统工程师任职要求
  16. 对三点雨流计数法的思考
  17. 2021语言与智能技术竞赛:机器阅读理解任务 实验报告
  18. [aapt包管理]aapt查询Apk最低支持的Android版本
  19. Africastar非洲百日记
  20. Qt exe程序缺少dll的解决方法

热门文章

  1. lect01_codes03_eg梯度下降
  2. 【算法】矩阵连乘(MatrixMultiply)
  3. 09 | 不可或缺的自定义函数
  4. CentOS 6.2下安装基于Suricata + Barnyard 2 + Base的入侵检测系统
  5. cmd中的arp指令
  6. modbus调试工具 linux,Modbus TCP的模拟器的Windows/Linux的
  7. 生产环境系统突然访问速度变慢问题排查
  8. ps cs6选择并遮住在哪设置
  9. 内部矩阵维度必须一致simulink_手把手教你将矩阵画成张量网络图
  10. 晶圆在低温探针台中的安装方式——N-Grease真空油脂和夹具