海量数据问题总结

本文概述了如何处理海量数据的频次统计、去重问题,包括TopK查询、哈希与位图方法,并介绍了中位数计算的内存优化策略。通过实例演示了如何在内存限制下找到高频IP、高频率词和热门查询,以及使用BitMap处理重复整数。
摘要由CSDN通过智能技术生成

一.频次统计/top1/topK/问题

这种问题通用的四步解决:

  • 第一步:Hash映射。对要统计的对象取Hash值,将该Hash值对K取模,根据取模结果将原本的大文件分割为K个小文件。
  • 第二步:Hash统计。在每个小文件中,利用Hash表统计对象的频次,这里要保证内存足够存放所有不同对象。(也可利用trie树进行频率统计)
  • 第三步:堆排序。对于TOPK问题,建立大小为K的最小堆,然后逐个读入统计后的对象,如果对象频次大于堆顶,则移除堆顶,将该元素加入堆中。由于堆的调整时间为log(K),因此遍历所有元素的时间复杂度为Nlog(K)。

如果数据不是很大,能够一次性载入内存中,也可用快排的Partition函数取topK
该方法时间复杂度为O(N),但需将所有元素都加入内存,且会改变原来都数组

  • 第四步:合并结果。将各个小文件的topK进行归并排序,最终得到整个文件的TopK

对应常见问题:

1、海量日志数据,提取出某日访问百度次数最多的那个IP。
2、有一个1G大小的一个文件,里面每一行是一个词,词的大小不超过16字节,内存限制大小是1M。返回频数最高的100个词。
3、假设目前有一千万个记录,请你统计最热门的10个查询串,要求使用的内存不能超过1G。
4、有10个文件,每个文件1G,每个文件的每一行存放的都是用户的query,每个文件的query都可能重复。要求你按照query的频度排序。(先将文件读入按照Hash映射重新分为10个文件,再按上述方法)
5、类似的问题很多,万变不离其宗

上面为这一问题的基本思路,在实际工作中遇到这一问题,可采用MapReduce框架解决(如Hadoop)

二.重复/去重问题

这种问题主要有两种解决方案:

1.分治+Hash去重+合并

该方案与上面的TopK问题思路类似:

  • 第一步:Hash映射。对要统计的对象取Hash值,将该Hash值对K取模,根据取模结果将原本的大文件分割为K个小文件。
  • 第二步:Hash去重。在每个小文件中,利用Hash表统计对象的频次,如果频次大于1,说明该对象重复
  • 第三步:合并结果。将上述小文件中不重复的对象合并,即得到最终不重复的结果。
2.位图(BitMap)

为了节省空间,可以采用位图的方法:即用1个(找出所有不同的数)或2个bit(找出所有去重后的数)表示一个数,然后通过该位的状态判断该数是否重复,是否存在

这里要注意,由于创建位图需要给定数组大小,因此需要先获得所有数的范围

时间复杂度为O(N)

下面以两个例子为例:

1.已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同的号码。

  • 因为号码为8位数,所以号码的范围为0-9999999共1亿个数,创建一个大小为1亿的bit数组,每个位置的下标对应一个电话号码(1亿bit数组只需占用十几MB的内存)
  • 挨个读取每个电话号码,如果该号码对应位置下标为0,则修改为1表示该号码存在
  • 遍历该bit数组,取出值为1的下标,即完成去重

2.2.5亿个整数中找出不重复的unsigned int整数的个数,内存空间不足以容纳这2.5亿个整数

由于该问题需要去除重复元素,因此不仅需要判断是否存在,还需判断是否重复,因此可用2bit表示一个数,其中0表示未出现,1表示出现一次,2表示出现2次及以上,在遍历这些数的时候,如果对应位置的值是0,则将其置为1;如果是1,将其置为2;如果是2,则保持不变。

  • 创建一个2^32大小的bit数组
  • 挨个读取每个数
  • 最终统计bit数组值为1的数

这一问题的拓展:求两个文件的交集;或给定一个数和一个包含大量数的文件,判断该数是否在该文件中出现过

这一问题也有两种处理方案:

方案一类似于上面的方案一:

  • 第一步:Hash映射。对要统计的对象取Hash值,将该Hash值对K取模,根据取模结果将原本的大文件分割为K个小文件。
  • 第二步:Hash统计。遍历第一个文件,建立起包含所有元素的hashSet
  • 第三步:判断重复。遍历第二个文件或给定的数,判断该数是否在之前的hashSet出现过

方案二是位图(BitMap)的扩展,即布隆过滤器(Bloom filter)

其思想是利用多个哈希函数给位图赋值。但要注意的是布隆过滤器会出现误判的情况,如判断某个数出现过,该数可能实际上没出现过(但是如果判断该数没出现过,则该数一定没出现过,具体原因见原理)

因此需要根据给定数的大小合理设置位图的大小,减少误判的几率

对应常见问题:

1.给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中?
2.给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url?

三.中位数问题

对于该问题,如果内存足够,当然最简单的方法是直接在内存中排序,然后取中位数即可

对于内存不够的情况,需要采用分桶法:

  • 将所有数划分为K个区域,然后读取数据并统计落到各个区域里的数的个数
  • 根据统计结果就可以判断中位数落到那个区域,同时知道这个区域中的第几大数刚好是中位数。
  • 然后第二次扫描落在这个区域中的那些数就可以了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值