关系型数据库的工做原理(一)

 

本文从"数据库是如何处理一个 SQL 查询的?"这一基本数据库操做来讨论关系数据库的工做原理。 算法

 

cost based optimization(基于成本的优化)

为了解成本,须要了解一下复杂度的概念,具体考虑时间复杂度,通常用O表示,对应某个算法(查询),对于其随着数据量的增长复杂度增长趋势,而非具体值,O给出了一个很好的描述。时间复杂度通常用最坏时间复杂度表示,除此还有算法内存复杂度,算法I/O复杂度。 数据库

归并排序:

归并排序是诸多排序算法中的一种,理解归并排序有助于以后的查询优化以及meger join链接。 数组

归并(merge):服务器

Fig.1 数据结构

归并排序的大概过程如图1所示:把两个长度为4(N/2)的已排序数组组合成一个有序的长度为8(N)的数组,总计算次数为8(N),即将两个长度为N/2的数组遍历次数。整个算法能够分为两步: 函数

  1. 分解:把整个大数组分解为多个小数组;
  2. 排序:几个小数组被(按顺序) 合并起来(使用 merge)构成大数组。

分解: oop

Fig.2 优化

如图2,将N维数组逐层分解为一元数组,分解次数为log(N)。 spa

排序 线程

Fig.3

从图3可知,merge的次数与分解的次数是一致的,每次merge对数组元素排序的次数是相同的(N,这里是8):

Step1: 4次merge,每次对2个元素排序,共4*2次运算。

Step1: 2次merge,每次对4个元素排序,共2*4次运算。

Step1: 1次merge,每次对8个元素排序,共1*8次运算。

故排序的总运算次数为N*log(N)。

 

算法伪代码:

array mergeSort(array a)

   if(length(a)==1)

      return a[0];

   end if

   //recursive calls

   [left_array right_array] := split_into_2_equally_sized_arrays(a);

   array new_left_array := mergeSort(left_array);

   array new_right_array := mergeSort(right_array);

   //merging the 2 small ordered arrays into a big one

   array result := merge(new_left_array,new_right_array);

   return result;

 

归并排序的扩展:

  1. merge 时能够没必要建立新数组,而是直接修改原数组,以减小内存,in_place算法即如此。
  2. 只对内存中正在处理的数据进行加载从而下降内存和磁盘占用,该类算法为external sorting。
  3. 把归并过程在多个进程/线程/服务器上执行,这即是hadoop关键步骤。

     

三种重要的数据结构:

数组

数据库中的表能够理解为数组,如图4:

Fig.4

每行表明一个对象;

每列表明一个对象属性,每一个属性有一个固定类型(integer, string…);

二维数组较好的抽象出了数据的存储,可是当对数据进行过滤尤为是有多个过滤条件时,难度很是大,因此用数组抽象数据是不可取的。

树(二叉树/B树)

二叉树是一种特殊树结构,知足一下特色:

左子树在整个对应分支最小,右子树在整个对应分支最大。如图5:

                                                   Fig.5        

这是一个简单的B树,共15个节点,如要找40,从根节点136开始,136>40,故查询根节点的左子树80,80>40,再查80的左子树,此时40=40。

对应具体问题,如图4,假设查询某位员工国籍(即column3字段)是UK的,可将国籍做为树节点进行搜索,找到节点值为UK,便可找到UK值所在的行,查询该表中的行,获得其余信息。

B树只须要log(N)次运算,可做为较好的索引搜索,节点存储值的类型能够是多种类型,只要有相应类型的对比函数,就能够进行一次或屡次查询过滤。

B+树

B树较好的解决了等值过滤问题,但当出现范围过滤时,就有较大麻烦,好比当要过滤图5中两个值之间数值时,复杂度达N,且为获取整个值不得不加载整个树,增长了I/O。B+树只在最后一层节点才存储数据,其余节点只作路由功能,如图6.

Fig.6

能够看到B+树的每一个叶子节点都指向其后续节点,所以当查询t->(M-t)范围内的数据时,复杂度为M+Log(N),相比B树N,当N很大时,B+树显然速度更快,且因不用遍历整棵树因此I/O很小。

Hash表

哈希表是一种经过元素的key快速查询到数据元素的数据结构,当数据库作查询操做时,经过哈希表更快。哈希表通常有几个部分:

  1. 给个元素定义一个key值
  2. 定义一个哈希函数,hash函数经过key找到元素位置(bucket)。
  3. 定义key值比较函数,经过key值比较函数,在找到的bucket查找对应的值。

                                                Fig.7

如图7,共10个bucket,哈希函数是modulo,好比此时要找59,经过hash函数找到bucket9,而后在bucket9中经过key值对比函数,59!=99,通过7次运算逐值对比发现没有59.

经上列可知,查询复杂度与hash函数相关,hash的值越多(bucket越多),bucket含有的值越少(key值深度越小),复杂度越低,但空间占用越大,hash值越小,则相反。若是哈希函数选择得足够好,那么查询的时间复杂度能够是 O(1)。

Hash与数组:

哈希表能够只将部分bucket存入内存(好比经常使用),其余的Bucket存入磁盘,而数组不得不分配一块连续内存空间,尤为当数组很大时,极困难。

 

----------------------

文章为How does a relational database work笔记,参考其中文翻译Franklin Yang。

相关文章
相关标签/搜索