排序
数据库系统中,数据排序有着重要的作用。其原因有两个:
- SQL查询会指明对结果进行排序;
- 连接运算能够得到高效实现(本文第二节会说到)。
外部排序归并算法(external sort-merge)
对于一个数据库来说,它往往具有海量的数据。若对这海量数据进行排序,是不能够一次性在内存中完成的,因此把不能全部放在内存中的关系的排序称为外排序,而外排序最常用的技术就是外部排序归并算法。
直观描述
举个最简单的例子来说明外部排序归并算法。下面对序列 2, 3, 1, 7, 9, 6, 8, 4, 5, 0 进行排序。首先使用最传统的二路归并排序算法:
如上图所示,第一次归并排序是两两元素合并并排序,第二次归并是将上一次排序好的元素进行重排,依此类推得到最终排序结果。
上述算法的前提是内存能够容纳所有排序元素,说白了就是要排序10个元素得至少有长度为10的数组来存它才行。如果数组长度不足10,一次只能排序3个元素怎么办?这就用到了外部排序的思想。
第一阶段,和之前一样,因为只能对3个元素进行排序,那就首先以3个元素为1组将其排好,这排好的三元组就称为归并段。
第二阶段,内存只能存储3个数据,这里为2个归并段各分配一个块用来进行比较,剩下的一块保存两元素比较的较小值作为输出结果。即从第一个归并段中取出1,从第二个归并段中取出6。将比较结果存入第三个块中,此时存入1,并将1存入到结果中。
由于1已经存入到结果中,接着应该从归并段1中将下一个元素缓存至内存,并将比较结果存入第三块之后输出,如下图所示。
依此类推,当一个归并段的元素全部用完后,加载下一个归并段重复上述过程,最终得到排序结果。
得到了排序结果,就能够将这一结果运用到连接当中。
连接
这一连接算法可用于计算自然连接和等值连接。该算法描述如下:
- 归并连接算法为每个关系(R和S)分配各一个指针(pr和ps);
- 首先顺序遍历关系R,将具有相同值元素暂存在缓冲区中;
- 顺序遍历关系S,遍历到元素的值大于等于缓冲区中的值,如果相等,则执行步骤4,否则返回步骤1。
- 顺序遍历缓冲区和关系S中的元素,并将相同元素加入连接结果中;当元素值不同时,返回步骤2,若任意指针为空,则结束连接。
下面用一个简单的例子来说明该算法。假设关系R为一数组2,3,3,5,5,6
,关系S为1,1,2,2,3,4,4,5
。注意,这里的数组都是已经排好序的,其排序算法正是本文第一节中提到的。
- 为两个关系各分配一个指针,此时
pr
指向R中的2,ps
指向S中的1,如下图所示。
- 顺序遍历关系R,相同元素只有2,因此将2加入缓冲区,当前缓冲区内元素为
{2}
,如下图所示:
- 顺序遍历关系S中的元素,由于缓冲区中元素为2,因此
ps
遍历到2时转到步骤4,如下图:
- 缓冲区中元素为
{2}
,ps指向2,因此将{2,2}
加入连接结果,ps指针随即指向下一个元素。ps指针仍然指向2,则需再次把{2,2}
加入到连接结果中,同时更新ps指针。此时ps指向的内容为3,本轮连接结束,返回步骤2。完成该步骤后指针如下图所示:
这时,连接结果中存有两个元组{(2,2), (2,2)}
。
同样的道理,再次执行步骤2,将元素3加入缓冲区,缓冲区中元素为{3,3}
,执行步骤3;当前ps指向为3,执行步骤4;将(3,3)
和(3,3)
加入到连接结果,ps和pr均不是空指针,则再次执行步骤2。依此类推得到最终结果。