布隆过滤器
文章参照和引用处:http://www.cnblogs.com/haippy/archive/2012/07/13/2590351.html
首先布隆过滤器解决的问题是:在一个非常大的数据集合里面判断一个数据是否存在。
常规的办法,可以使用一个hash哈希函数,但是非常消耗空间。我们不禁想到如何节省空间,这个时候布隆过滤器就出现了。我们可以在bit位上做文章。
例如左神列举的例子:100亿个url,url长度64字节。如果用常规的hash表,仅存储url就要花去6400亿字节,即640G,这个hash表就非常的恐怖了。如何解决:我们将使用k个hash函数,这k个hash函数相互之间是独立的,然后我们使用一个长度为m位(bit)的数组(初始都为0)。每一个hash函数计算hash值,取模m,得到一个idx,将m位中的第idx位置标记1,所以每添加一个 url 共有k位被置1。每次判断url是否存在,就通过k个hash算出来(利用hash函数的特性:相同的输入,会有相同的输出),得到k个idx,判断是否为1。如果都为1,则存在,否则就不存在。
k:hash函数的个数。
m:总数组的bit位数,如int类型数据4个字节,32bit,那么M就是32。
idx:hash函数计算,取模后,得到的一个m值。每一个hash函数对每一个url都可以算出一个特定的m值。
p:表示失误率。
n:表示总数据个数。如果100亿个url,n就等于100亿。
优点:极大的节省了空间,我们把空间的关注点,从url的大小移除了,不管你url是64字节,还是640字节,甚至6400字节。都与我无关,我的空间大小取决于:失误率的控制范围。
缺点:布隆过滤器就出现失误率(False Positive)了,世上真没有完美的东西,想想为什么会出现失误率,本人的理解是:k个hash算出来的bit位,可能会出现重复。这个hash函数本来没有标记为1,但是另一个之前的hash函数把这个位置标记为1了,所以就冤枉了。
主要的公式:
如何确定空间m(注意单位是bit)大小:
如何计算p:
如何计算hash函数的个数:
False positives 概率推导
假设 Hash 函数以等概率条件选择并设置 Bit Array 中的某一位,m 是该位数组的大小,k 是 Hash 函数的个数,那么位数组中某一特定的位在进行元素插入时的 Hash 操作中没有被置位的概率是:
那么在所有 k 次 Hash 操作后该位都没有被置 "1" 的概率是:
如果我们插入了 n 个元素,那么某一位仍然为 "0" 的概率是:
因而该位为 "1"的概率是:
现在检测某一元素是否在该集合中。标明某个元素是否在集合中所需的 k 个位置都按照如上的方法设置为 "1",但是该方法可能会使算法错误的认为某一原本不在集合中的元素却被检测为在该集合中(False Positives),该概率由以下公式确定:
其实上述结果是在假定由每个 Hash 计算出需要设置的位(bit) 的位置是相互独立为前提计算出来的,不难看出,随着 m (位数组大小)的增加,假正例(False Positives)的概率会下降,同时随着插入元素个数 n 的增加,False Positives的概率又会上升,对于给定的m,n,如何选择Hash函数个数 k 由以下公式确定:
此时False Positives的概率为:
而对于给定的False Positives概率 p,如何选择最优的位数组大小 m 呢,
上式表明,位数组的大小最好与插入元素的个数成线性关系,对于给定的 m,n,k,假正例概率最大为:
下图是布隆过滤器假正例概率 p 与位数组大小 m 和集合中插入元素个数 n 的关系图,假定 Hash 函数个数选取最优数目: