100亿数据排序问题
100亿排序问题:内存不足,一次只允许你装载和操作1亿条数据,如何对100亿条数据进行排序。假设结果要求升序 可以理解为如何给100亿个数字排序
基本思路
第一步:数据拆分成若干个小文件
假设100亿个数据存在一个大文件中,一次只能操作1亿条数据,显然要拆分来排序,那就分出100个文件,每个文件1亿条数据。
那数据怎么拆分呢?不可能把所有数据读取出来再拆分,因为内存不够。
可以使用fs.createReadStream来每次读取部分文件流(注意fs.readFile是一次把文件放到内存中再操作)
这样每次从大文件中读取一部分数据放入小文件,直到平均拆分成100个小文件。
第二步:对100个小文件里的数据先进行排序
队100个小文件进行排序,可以用快速排序、归并排序、堆排序等等。
第三步:难点是如何将100个小文件进行合并并排序
- 先创建一个文件,用来存放最终结果
- 100个小文件已经排好序了,假设是升序。遍历100个文件,每个文件取出第一个数字也就是最小值,组成(数字,文件名)的组合加入到一个数组中。这样最后得到一个有100项,每项是数字+文件名的数组,然后对数组排序,得到一个升序的数组。
- 然后重点来了,这里要注意理解。每次取出数组的第一个数字也就是最小值放入结果文件,然后再从这个数字对应的文件取出一个最小值放入数组中,然后再对数组进行排序,再把数组的最小值取出来放入结果文件,再到对应的文件取最小值放入数组进行排序,以此类推,直到100个文件里数字取完,以及数组取完,此时最终结果文件里的全部数字都是有序的了。
- 注意理解为什么要到数组最小值对应的文件再取数字?因为数组的最小值被取出后,其他文件的最小值都还在数组里,这个数组永远都是一个最小值集合的数组。
思维拓展
- 类似的100亿个数字求和,求中位数,求平均数,套路就是一样的了。
- 求和:统计每个小文件的和,返回给master再求和就可以了。
- 求平均数:上面能求和了,再除以100亿就是平均数了
- 求中位数:在排序的基础上,遍历到中间的那个数就是中位数了。