大文件 多路归并 排序

1 题目

这一种题目的描述,大概有以后两种:

  • 题目1:一个大文件在一台服务器上存不下,需要存放在多台服务器上,将这个大文件的内容进行排序。
  • 题目2:一个大文件100G,存储在磁盘上,现在需要对这个文件的内容进行排序,而内存装不下整个文件。

2 分割为小文件+多路归并排序

大文件 多路归并 排序
基本思路:

  1. step1:分割+排序
    从头开始将大文件FileFile的一个小部分读入内存中,将这一小部分进行排序,然后将排序后的这一小部分写入到一个独立的小文件file1file_1中。循环前面的步骤,生成了一堆内部有序的小文件file1file_1file2file_2file3file_3、… 、fileNfile_N
  2. step2:多路归并
    将每一个小文件的第一个数取出,即每一个小文件里的最小数,对这些数进行归并排序,将这些数里的最小数字numinum_i(来自fileifile_i )写入大文件的第一行,此即整个大文件里的最小数字。
    将文件fileifile_i的行数指针+1,取出文件fileifile_i行数指针当前所指的数字,放入内存中,将大文件的行数指针+1。
    继续前面的循环,直到所有小文件都遍历完成。
    参考文献:100G 数据,只有 100M 内存,怎么排序?

3 归并排序程序

4 具体的描述

海量数据排序——如果有1TB的数据需要排序,但只有32GB的内存如何排序处理?
1、外排序
  传统的排序算法一般指内排序算法,针对的是数据可以一次全部载入内存中的情况。但是面对海量数据,即数据不可能一次全部载入内存,需要用到外排序的方法。外排序采用分块的方法(分而治之),首先将数据分块,对块内数据按选择一种高效的内排序策略进行排序。然后采用归并排序的思想对于所有的块进行排序,得到所有数据的一个有序序列。

例如,考虑一个1G文件,可用内存100M的排序方法。首先将文件分成10个100M,并依次载入内存中进行排序,最后结果存入硬盘。得到的是10个分别排序的文件。接着从每个文件载入9M的数据到输入缓存区,输出缓存区大小为10M。对输入缓存区的数据进行归并排序,输出缓存区写满之后写在硬盘上,缓存区清空继续写接下来的数据。对于输入缓存区,当一个块的9M数据全部使用完,载入该块接下来的9M数据,一直到所有的9个块的所有数据都已经被载入到内存中被处理过。最后我们得到的是一个1G的排序好的存在硬盘上的文件。

2、1TB数据使用32GB内存如何排序
  ①、把磁盘上的1TB数据分割为40块(chunks),每份25GB。(注意,要留一些系统空间!)
  ②、顺序将每份25GB数据读入内存,使用quick sort算法排序。
  ③、把排序好的数据(也是25GB)存放回磁盘。
  ④、循环40次,现在,所有的40个块都已经各自排序了。(剩下的工作就是如何把它们合并排序!)
  ⑤、从40个块中分别读取25G/40=0.625G入内存(40 input buffers)。
  ⑥、执行40路合并,并将合并结果临时存储于2GB 基于内存的输出缓冲区中。当缓冲区写满2GB时,写入硬盘上最终文件,并清空输出缓冲区;当40个输入缓冲区中任何一个处理完毕时,写入该缓冲区所对应的块中的下一个0.625GB,直到全部处理完成。

3、继续优化
  磁盘I/O通常是越少越好(最好完全没有),那么如何降低磁盘I/O操作呢?关键就在第5和第6步中的40路输入缓冲区,我们可以先做8路merge sort,把每8个块合并为1路,然后再做5-to-1的合并操作。
  再深入思考一下,如果有多余的硬件,如何继续优化呢?有三个方向可以考虑:
  使用并发:如多磁盘(并发I/O提高)、多线程、使用异步I/O、使用多台主机集群计算。
  提升硬件性能:如更大内存、更高RPM的磁盘、升级为SSD、Flash、使用更多核的CPU。
  提高软件性能:比如采用radix sort、压缩文件(提高I/O效率)等。

————————————————
版权声明:该部分为CSDN博主「无鞋童鞋」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/FX677588/article/details/72471357