大数据处理”套路“

429 阅读4分钟

大数据处理思路: 分而治之/hash映射 + HashMap统计 + 堆/快速/归并排序。

一、海量数据里求 Top K(有重复数据)

海量数据意味着不能仅在内存解决,把数据分批存在小文件里,比如说1000个文件

  1. 对每条数据进行 hash 取模,hash(data) % 1000,假设 hash 函数使数据可以均匀分布,取模后放到相应的小文件里。
  2. 遍历每个小文件,使用 HashMap 存放数据出现的频率,HashMap 的 key 为数据本身,value 为频率,然后把这个关系存放到另一个文件里,也就是说最后会有 1000 个数据与频率映射关系的文件。
  3. 初始化一个容量为 K 的最小堆,然后遍历这 1000 个数据与频率映射关系的文件,如果词频大于最小堆里的最小值,那么弹出这个最小值,写入这条数据,也就是说,遍历过程中最小堆里面保存的始终是当前的 Top K,最后得到的最小堆即为 Top K。

关键思想

  1. 相同的数据经过 hash 函数的结果肯定是一样的,也就保证了某条数据肯定只存在某个文件里,不会分散到其他文件里。
  2. 上面分为 1000 个文件只是举例,实际可以根据内存限制来决定。
  3. 为什么使用最小堆?
    • 最小堆要求父节点要比左右子节点小,所以根节点即为最小值,所以获取最小值的时间复杂度为 O(1)。
    • 最小堆是一颗完全二叉树,插入的时间复杂度只跟树的高度有关,假设堆里有 K 个元素,那么时间复杂度就是 O(log K)
  4. 第三步也可以采用归并排序来求 Top K。

二、海量数据根据词频排序

第一步和第二步跟 一、 基本一致

  1. 对若干个小文件进行归并排序
多个小文件归并排序(升序)步骤:

1. 对每个小文件里的数据进行升序排序
2. 取出每个文件里的第一个数进行比较,把最小的数写到大文件里,继续取这个最小数的文件的下一个数进行比较,循环这个步骤,直到所有小文件的数据都处理完成

优化:

1. 为每个小文件设置输入缓冲区,每次读取输入缓冲区大小的数据进行比较;
2. 设置一定大小的输出缓冲区,输出缓冲区满了才把排序好的数据写到大文件;
3. 输入缓存区和输出缓冲区设置的大小根据内存限制而定。
其他排序方式:

1. 计数排序,稳定的非比较的排序方式,使用一个额外的辅助数组/计数数组C,其中第i个元素是待排序数组A中值等于i 的元素的个数。然后根据数组C来将A 中的元素排到正确的位置。时间复杂度基于范围中最大的数k和长度n,为O(k+n)。
2. 位图排序,已知所有的数字只出现一次,我们就可以只使用计算排序中的记录函数,将所有存在的值对应的位置设置为1,否则对应为0,扫描整个数组输出位置为1对应的下标即可完成排序。
3. 桶排序,将数据分装到有限数量的桶里,分桶的时候保证buckets[i] < buckets[i+1],分别对桶里数据进行排序,最后按桶顺序把里面的数据拼起来即可。
4. 快速排序。

三、海量数据中查找出重复数据

第一步跟 一、 一致

经过 hash 取模后,可能重复的数据肯定会在同一文件里,所以只要遍历这些文件,每个文件都使用一个不同的 HashSet 来判断是否有重复数据即可。

参考

大数据处理 - 分治/hash/排序

海量数据排序——如果有1TB的数据需要排序,但只有32GB的内存如何排序处理?

海量数据处理--重新思考排序(2)

算法从入门到“放弃”(5)- 计数排序