对于不能所有放在内存中的关系的排序。就须要引入外排序,其中最经常使用的技术就是外部归并排序。算法
外部排序分为两个阶段函数
Phase1 - Sorting优化
对主存中的数据块进行排序,而后将排序后的数据块写回磁盘。code
Phase2 - Mergingblog
将已排序的子文件合并成一个较大的文件排序
从2路归并排序开始。来引出N路归并排序算法索引
能够见下图内存
对于简单的二路归并。咱们有两个buffer能够用。一个用来放输入进行排序获得归并块。而另外一个则用来放输出ci
下面来分析一下二路归并的时间复杂度hash
在每个阶段咱们都须要把归并块从磁盘中读入。而后在写回磁盘所以总共的I/O次数就是阶段数 * 2
阶段数能够很容易的获得为
能够很容易的发现上面的问题主要出如今。因为咱们的输入缓冲区只能放一个page。因此这致使了咱们不停的进行换入换出致使了io次数变得很是多。优化方法就是加大缓冲区大小。减小阶段数。这就须要咱们归并路数增大。
使用B buffer pages 这样咱们的输入缓冲区就能够放B - 1个page。这样咱们的阶段数就能够减小了。
若是咱们的table中已经有了B+树索引。那么咱们能够利用它进行优化。
这里有两种状况须要被考虑
聚簇索引
数据的物理地址顺序和索引的顺序是一致的。
这种方法比外部排序要好,由于它没有额外的计算。好比不须要进行sort。不须要进行归并。并且全部的磁盘访问都是顺序的。
非聚簇索引
数据的物理地址顺序和索引的顺序是不一致的。
若是是这样的索引。就利用外部排序就好。
将多个元组折叠为单个标量值。有两种实现方法
1. 排序
排序以后相同的元素就会在排在一块儿。这样就能够去除冗余元素
2. hash
可是若是咱们不要求数据是有序的。这样咱们排序就至关于浪费了时间。由于排序起码要花费nlogn的时间。好比GROUP BY
和DISTINCT
操做。在这种状况下。hashing就是一个更好的选择
1. Partition
假设咱们有B buffers。其中B - 1个buffer用来partitions而1个buffer用来存储输出data。
第一阶段就是利用一个hash函数。把tuple哈希到不一样的桶中。
2. Rehash
因为阶段1以后。拥有相同cid值的tuple都被映射到了相同的桶内。这个阶段咱们对不一样的桶在进行一次hash。就能够完成咱们的去重操做。
固然利用hash操做不只能够进行去重还能够进行其余的操做。如MAX、MIN、AVG、COUNT、SUM等
下面这张图演示了count操做和sum操做。
这张图演示了avg操做就是利用 sum / count
这个算是结合cmu15-445课程和对应的教材、ppt进行的总结。顺序从10开始是由于如今正好看到这里。而以前忘了整理了。会在后面全部的都看完以后进行整理的。