基于B族树的关系型数据库IO瓶颈分析

来源:互联网 发布:通用字体软件下载 编辑:程序博客网 时间:2024/04/30 08:08

前言


传统关系型数据库,也就是建立在关系模型基础之上的数据库。关系型数据库本身基于关系代数的数学理论关系模型是70年代埃德加·科德首次提出的,而该模型成为了关系型数据库的基础。目前市面上众多的传统关系型数据库均是基于B族树实现的,至于传统关系型数据库的众多特性这里就不进行论述了,在这里只想分析一下基于B族树的传统关系型数据库的IO瓶颈。

基于B族树的数据库IO瓶颈分析

磁盘属于外存储器的一种,其特点是容量非常大,价格相对低廉,但是存取速度有限,尤其是随机存取速度还是很慢的。磁盘IO操作中磁头反复移动会耗费很多时间,因此进行随机的读写时,磁盘磁头的转动所花费的时间是相当可观的,造成了随机读写速度非常的慢。此外,磁盘读写是以数据块为基本单位,每次都要读取数据时要把包含该数据的数据块读出来。因此数据顺序存放能够加速磁盘的读写速度。总的来说,磁盘是容量大价格低廉的存储设备,磁盘随机读写会造成磁头频繁的移动,开销很大,要尽量避免这种开销。

传统的关系型数据库一般采用B族树(B树、B+树等)作为存储的基础数据结构。B族树是一种多路平衡搜索树,其作为数据库的基础数据结构的最大优点是效率很高,可以有效的降低磁盘IO。下面再仔细分析一下B树:

我们设有一颗阶数为m(M应该大于等于2)的B树,那么该树中的每个节点最多有m个孩子,除此之外还有如下特点:

若根节点有孩子(也即非叶子节点),则其至少有2个孩子;

所有的叶子节点都在同一层;

除了根节点,其他每个非叶子节点至少有upper(m/2)个子树,upper为向上取整;

非叶子层存有指向下一层的指针,根据本层的数据和下一层的数据将指针指向合适的位置,指针指向下一层位置左边的数据小于指针位置的数据,而指针指向下一层位置右边的数据大于指针本层位置的数据,这样就完成了一层一层的索引关系。

对一棵B树进行查找数据时,会从根节点开始,根据要找数据的key与当前的key进行比较,一层一层的向下查找,直到找到该key或者到达叶子节点时仍未找到为止。每个节点都是存储在磁盘中,那么不难看出,一共最多需要树的高度次磁盘IO(这里忽略掉内存读取与CPU的开销,因为与磁盘IO相比这些开销非常非常小)。那么B树的高度是多少呢? 是logm((n+1)/2)+1,推导请查阅算法导论等书籍即可。这里我们设B为(n+1)/2,那么树的高度为logm(B)+1,也就是说基于B树的数据库,进行一次key查询(基于数值点的查询)需要最多访问logm(B)+1次磁盘,这个效率其实还是很高效的。

下面讨论对一棵基于B族树的数据库进行插入操作。插入一个数据,需要从根节点开始进行比较,一层一层的向下找合适的位置,最终将值插入到B族树中。若对一个新建的数据库,对该数据库进行大量数据插入操作,如果这些数据已经排好顺序了,那么每次的插入操作在磁盘的位置都会紧挨着上一次的操作位置,这样这些操作写到磁盘中都会是顺序写,因此效率比较高。但是若要插入的大量数据都是随机且未排序的,那么这些数据所在的块在磁盘中就不会挨着,因此也就是会造成大量的随机写操作,其插入效率会非常的低下。插入数据的操作是数据库中经常发生的操作,若随机的插入大量数据,很难避免大量的磁盘随机写,磁头频繁的移动消耗掉大量的时间,因此对于随机的大量数据插入操作,磁盘IO是很严重的性能瓶颈。

下面讨论一下对一棵基于B族树的数据库进行范围查询。对于一棵新创建的B族树,其叶子节点在磁盘上通常是顺序存放的,对其进行范围查询时,会对磁盘进行大量的顺序读操作,由于是顺序的读,不需要频繁的移动磁头,因此其效率非常的高,速度非常的快。相比于新创建的B族树,若是一棵经过大量插入、删除、修改的B族树就没有这样的范围查询性能了。一棵使用过(插入、删除、修改等操作)很久的B族树,进行范围查询时,由于叶子节点将会散布到磁盘的各个地方,因此会造成大量的随机磁盘读操作,造成磁头的频繁移动,消耗大量的时间,因此效率是十分低下的,磁盘将成为范围查询的瓶颈。

总的来说,对基于B族树的数据库进行插入操作与范围查找(使用很久的B族树)时会有大量的随机磁盘IO,因此其性能并不是很好。


解决方法

针对前面分析的瓶颈,我们在这里尝试去寻找解决这些问题的方法。磁盘IO瓶颈一直是数据库需要面临的问题,这里所说的插入与范围查询只是特点比较鲜明、对性能损失比较大的操作。解决这一类问题我们有两种思路:其一为加快磁盘的读写速度;其二为尽力避免随机读写,将随机读写转化为部分随机甚至小部分随机,乃至全部顺序读写。

针对第一种思路,我们可以使用性能更加好的磁盘,甚至使用SSD代替传统磁盘。一种比较好的方法是使用SSD,在内存和磁盘之间再加一层缓存,这样可以兼顾效率和花费,性价比比较好。目前facebook出的flashcache就可以实现这一功能,将其应用在mysql上,能够显著的提升mysql的性能。

针对第二种思路,我们可以改换B族树为其他的数据结构,例如要改善插入性能可以使用基于追加日志的方式实现数据库,所有插入数据都写到日志的尾端,因此插入操作变成了顺序磁盘IO,效率会非常的高。此外使用分形树等技术也可以。关于分形树等较新的数据库技术,以后有时间再写专门介绍的文章。

小结

基于B族树的一些传统关系型数据库在面对海量数据以及海量操作时会有严重的磁盘IO瓶颈,例如随机插入数据,范围查找等操作的效率并不高,可以根据实际的需求来调整数据库,开发出符合新需求的数据存储产品。