(转)预估大数据量下UV的方法
在实际应用中,我们经常碰到这种情况,即要统计某个对象或者事件独立出现的次数。对于较小的数据量,这很容易解决,我们可以首先在内存中对序列进行排序,然后扫描有序序列统计独立元素数目。其中排序时间复杂度为O(n*log(n)),扫描时间复杂度为O(n),所以总的时间复杂度为O(n*log(n))。当内存非常充裕时,我们还可以考虑使用哈希,将时间复杂度降到O(n)。尤其是当元素只能取有限范围的整数值时,我们还可以使用BitMap节约内存。但是在处理数据流序列时,比如,google的独立访问IP统计,由于序列非常长,元素取值范围可能比较广,单个元素占用内存可能比较多,导致内存中无法容纳整个序列,甚至无法容纳整个独立元素集合。此时,不论是基于排序还是基于哈希的方法都不具备可行性。
Flajolet-Martin(FM)算法能够较好地解决估算数据流序列中独立元素数目的问题。
假设我们有1万个int型数字(可重复的),我们想找出这个数字集合中不重复的数字的个数。怎么办呢?很简单,将这1万个数字读进内存,存放到hashset中,那么hashset的size就是不重复数字的个数。接下来,问题变得更加的复杂,有100亿个数字,怎么办? 全部读取到内存中可能会有问题,如果这其中有1亿个不重复的数字,那么至少需要内存 100M * sizeof(int),内存也许不够。 FM算法就是为了解决这个问题。假设n个object,其中有m个唯一的,那么FM算法只需要log(m)的内存占用(实际操作中会是k*log(m)),以及O(n)的运算时间。当然,FM的问题是,它的结果只是一个估计值,不是精确结果。
具体思路如下:
假定哈希函数H(e)能够把元素e映射到[0, 2^m-1]区间上;再假定函数TailZero(x)能够计算正整数x的二进制表示中末尾连续的0的个数,譬如TailZero(2) = TailZero(0010) = 1,TailZero(8) = TailZero(1000) = 3,TailZero(10) = TailZero(1010) = 1;我们对每个元素e计算TailZero(H(e)),并求出最大的TailZero(H(e))记为Max,那么对于独立元素数目的估计为2^Max。
这种估算的理论依据证明参见 原文。
举例来说,给定序列{e1, e2, e3, e2},独立元素数目N = 3。假设给定哈希函数H(e),有:
H(e1) = 2 = 0010,TailZero(H(e1)) = 1
H(e2) = 8 = 1000,TailZero(H(e2)) = 3
H(e3) = 10 = 1010,TailZero(H(e3)) = 1
第1步,将Max初始化为0;
第2步,对于序列中第1项e1,计算TailZero(H(e1)) = 1 > Max,更新Max = 1;
第3步,对于序列中第2项e2,计算TailZero(H(e2)) = 3 > Max,更新Max = 3;
第4步,对于序列中第3项e3,计算TailZero(H(e3)) = 1 ≤ Max,不更新Max;
第5步,对于序列中第4项e2,计算TailZero(H(e2)) = 3 ≤ Max,不更新Max;
第6步,估计独立元素数目为N’ = 2^Max = 2^3 = 8。
在这个简单例子中,实际值N = 3,估计值N’ = 8,误差比较大。此外,估计值只能取2的乘方,精度不够高。
在实际应用中,为了减小误差,提高精度,我们通常采用一系列的哈希函数H1(e), H2(e), H3(e)……,计算一系列的Max值Max1, Max2, Max3……,从而估算一系列的估计值2^Max1, 2^Max2, 2^Max3……,最后进行综合得到最终的估计值。具体做法是:首先设计A*B个互不相同的哈希函数,分成A组,每组B个哈希函数;然后利用每组中的B个哈希函数计算出B个估计值;接着求出B个估计值的算术平均数为该组的估计值;最后选取各组的估计值的中位数作为最终的估计值。
举例来说,对于序列S,使用3*4 = 12个互不相同的哈希函数H(e),分成3组,每组4个哈希函数,使用12个H(e)估算出12个估计值:
第1组的4个估计值为<2, 2, 4, 4>,算术平均值为(2 + 2 + 4 + 4) / 4 = 3;
第2组的4个估计值为<8, 2, 2, 2>,算术平均值为(8 + 2 + 2 + 2) / 4 = 3.5;
第3组的4个估计值为<2, 8, 8, 2>,算术平均值为(2 + 8 + 8 + 2) / 4 = 5;
3个组的估计值分别为<3, 3.5, 5>,中位数为3.5;
因此3.5 ≈ 4即为最终的估计值。
分析FM算法的时间复杂度。假定序列长度为N,哈希函数H(e)的数目为K。初始化K个Max值的时间复杂度为O(K);对N个元素e使用K个哈希函数H(e)计算TailZero(H(e))并更新Max值的时间复杂度为O(N*K);综合K个Max值给出最终估计值的时间复杂度为O(K)。因此总的时间复杂度为O(N*K)。
分析FM算法的空间复杂度。该算法需要存储K个Max值,而每个元素e在进行相关计算后就可以丢掉。因此总的空间复杂度为O(K)。
综上所述,FM算法的时间复杂度为O(N*K),空间复杂度为O(K)。一般来说K比较小,可以认为FM算法的时间复杂度为O(N),空间复杂度为O(1)。
FM算法可以用于估算独立Cookie数目,独立URL数目,独立邮箱地址数目等等。
(转)预估大数据量下UV的方法的更多相关文章
- 大数据量下MySQL插入方法的性能比较
不管是日常业务数据处理中,还是数据库的导入导出,都可能遇到需要处理大量数据的插入.插入的方式和数据库引擎都会对插入速度造成影响,这篇文章旨在从理论和实践上对各种方法进行分析和比较,方便以后应用中插入方 ...
- c#中@标志的作用 C#通过序列化实现深表复制 细说并发编程-TPL 大数据量下DataTable To List效率对比 【转载】C#工具类:实现文件操作File的工具类 异步多线程 Async .net 多线程 Thread ThreadPool Task .Net 反射学习
c#中@标志的作用 参考微软官方文档-特殊字符@,地址 https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/toke ...
- 大数据量下的SQL Server数据库自身优化
原文: http://www.d1net.com/bigdata/news/284983.html 1.1:增加次数据文件 从SQL SERVER 2005开始,数据库不默认生成NDF数据文件,一般情 ...
- mysql大数据量下的分页
mysql大数据量使用limit分页,随着页码的增大,查询效率越低下. 测试实验 1. 直接用limit start, count分页语句, 也是我程序中用的方法: select * from p ...
- 大数据量下,分页的解决办法,bubuko.com分享,快乐人生
大数据量,比如10万以上的数据,数据库在5G以上,单表5G以上等.大数据分页时需要考虑的问题更多. 比如信息表,单表数据100W以上. 分页如果在1秒以上,在页面上的体验将是很糟糕的. 优化思路: 1 ...
- mysql百万级别重排主键id(网上的删除重建id在大数据量下会出错)
网上教程: 先删除旧的主键 再新建主键 :数据量少时没问题,不会出现主键自增空缺间隔的情况(如:1,2,3,5):但是大数据量时会出现如上所述问题(可能是内部mysql多进程或多线程同时操作引起问题) ...
- boost的asio接收单路大数据量udp包的方法
开发windows客户端接收RTP视频流,当h264视频达到1080P 60fps的时候,按包来调用recvfrom的函数压力比较大,存在丢包的问题,windows的完成端口的性能效果当然可以解决这个 ...
- 大数据量下的集合过滤—Bloom Filter
算法背景 如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起来,然后通过比较确定.链表.树.散列表(又叫哈希表,Hash table)等等数据结构都是这种思路,存储位置要么是磁盘 ...
- (转)大数据量下的SQL Server数据库优化
在SQL Server中,默认MDF文件初始大小为5MB,自增为1MB,不限增长,LDF初始为1MB,增长为10%,限制文件增长到一定的数目:一般设计中,使用SQL自带的设计即可,但是大型数据库设计 ...
随机推荐
- MySQL服务器的运维与优化
MySQL运维 安装数据库 配置本地yum源,将gpmall-repo文件上传至/opt目录 创建yum.repo文件 安装mariadb服务 # yum install -y mariadb mar ...
- opencv —— inpaint 图像修补、去除指定区域物体
实现图像修补.物体去除:inpaint 函数 void inpaint(InputArray src, InputArray inpaintMask, OutputArray dst, double ...
- C++中static关键字的用法
运行一个完整的程序.我们可将整个存储区分为四块: (1)栈区:就比如局部变量,对应的函数参数等这些,调用完之后相应的内存会自己释放掉,很让人省心. (2)堆区:堆来堆去的.得要人动手.所以得我们自己手 ...
- c# 关于抓取网页源码后中文显示乱码的原因分析和解决方法
原因分析:首先,目前大多数网站为了提升网页浏览传输速率都会对网站内容在传输前进行压缩,最常用的是GZIP压缩解压解压算法,也是支持最广的一种. 因为网站传输时采用的是GZIP压缩传输,如果我们接受we ...
- #《Essential C++》读书笔记# 第七章 异常处理
基础知识 异常处理机制有两个主要成分:异常的鉴定和发出,以及异常的处理方式.通常,不论是membe function和non-member function,都有可能产生异常以及处理异常.异常出现后, ...
- 小白的linux笔记4:几种共享文件方式的速度测试——SFTP(SSH)/FTP/SMB
测试一下各个协议的速度,用一个7205M的centos的ISO文件上传下载.5Gwifi连接时,本地SSD(Y7000)对服务器的HDD: smb download 23M/s(资源管理器) smb ...
- iMacros 入门教程-基础函数介绍(2)
imacros 的 pos 参数是什么意思 position的缩写,如果有 2 个以上的元素共用完全相同的属性(比方说同一个小区的同一栋楼),这个 POS 的参数可以借由不同位置来帮助明确定位(也就是 ...
- 解决mysql导入导出错误问题
1.datetime类型: 当datetime的值为0000-00-00:00:00:00时,mysql是不接受此条数据的,当然可以 insert ignore into table--------- ...
- w13scan扫描器的使用
0x01 w13scan第三方包下载 环境:python3以上 下载:pip install w13scan 0x02 利用w13scan API接口编写w13scan.py from W13SCAN ...
- java 测试 (junit+ junit 断言 + postman)
实际开发中,除了开发,我想测试也是必不可少的一环吧.从简单的@Test .main 方法测试 到 页面测试 ,断言,postman. bug是无处不在,随时发生的事,高效率的调试.检测可以节省大量的开 ...