add bloom filter
This commit is contained in:
@@ -58,6 +58,7 @@ SVM
|
||||
学好python
|
||||
|
||||
|
||||
http://julyedu.com/course/getDetail?course_id=34#discard julyedu 课程大纲
|
||||
|
||||
|
||||
### 数据挖掘
|
||||
|
||||
+13
-9
@@ -231,7 +231,7 @@ trie,又称为前缀树或字典树,是一种有序树,用于保存关联
|
||||
|
||||
### trie树存储结构和基本操作
|
||||
|
||||
最简单实现 ---- 26个字母表 a-z (没有考虑数字,大小写,其他字符)
|
||||
最简单实现 ---- 26个字母表 a-z (没有考虑数字,大小写,其他字符如=-*/)
|
||||
|
||||
子树用数组存储,浪费空间;如果系统中存在大量字符串,且这些字符串基本没有公共前缀,trie树将消耗大量内存
|
||||
如果用链表存储,查询时需要遍历链表,查询效率有所降低
|
||||
@@ -249,8 +249,7 @@ int Trie_delete(Trie *trie,char *word);// 删除一个单词
|
||||
|
||||
```
|
||||
|
||||
trie树的增加和删除都比较麻烦,但索引本身就是写少读多,是否考虑添加删除的复杂度上升,依靠具体场景决定
|
||||
|
||||
trie树的增加和删除都比较麻烦,但索引本身就是写少读多,是否考虑添加删除的复杂度上升,依靠具体场景决定。
|
||||
|
||||
|
||||
DATrie libdatrie 双数组可以减少内存的使用量
|
||||
@@ -269,16 +268,21 @@ double-array trie 参考作者的这篇论文 http://linux.thai.net/~thep/datri
|
||||
|
||||
查询效率比hash table 更优??
|
||||
|
||||
trie 树比较费内存空间,在处理大数据时会内存吃紧
|
||||
|
||||
|
||||
知乎这里有个问题:`10万个串找给定的串是否存在`, 对trie合适hash给出了讨论。 http://www.zhihu.com/question/27168319
|
||||
|
||||
|
||||
### trie应用
|
||||
|
||||
典型应用是:前缀查询 , 字符串查询,排序
|
||||
典型应用是:前缀查询,字符串查询,排序
|
||||
|
||||
用于统计,排序和保存大量的字符串(但不仅限于字符串)
|
||||
经常被搜索引擎系统用于文本词频统计
|
||||
排序大量字符串
|
||||
用于索引结构
|
||||
敏感词过滤
|
||||
* 用于统计,排序和保存大量的字符串(但不仅限于字符串)
|
||||
* 经常被搜索引擎系统用于文本词频统计
|
||||
* 排序大量字符串
|
||||
* 用于索引结构
|
||||
* 敏感词过滤
|
||||
|
||||
### 实际应用问题
|
||||
1. 给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,求第一次出现在第几个位置
|
||||
|
||||
+99
-23
@@ -7,6 +7,20 @@
|
||||
针对空间,就一个办法,大而化小,分而治之。常采用hash映射
|
||||
|
||||
|
||||
### 估算
|
||||
|
||||
在处理海量问题之前,我们往往要先估算下数据量,能否一次性载入内存?如果不能,应该用什么方式拆分成小块以后映射进内存?每次拆分的大小多少合适?以及在不同方案下,大概需要的内存空间和计算时间。
|
||||
|
||||
比如,我们来了解下以下常见问题`时间` 和 `空间` 估算 :
|
||||
|
||||
```
|
||||
8位的电话号码,最多有99 999 999个
|
||||
IP地址
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
海量处理问题常用的分析解决问题的思路是:
|
||||
|
||||
* 分而治之/Hash映射 + hash统计/trie树/红黑树/二叉搜索树 + 堆排序/快速排序/归并排序
|
||||
@@ -17,25 +31,19 @@
|
||||
* 分布处理之 Hadoop/Mapreduce
|
||||
|
||||
|
||||
### 估算
|
||||
|
||||
在处理海量问题之前,我们往往要先估算下数据量,能否一次性载入内存?如果不能,应该用什么方式拆分成小块以后映射进内存?每次拆分的大小多少合适?
|
||||
|
||||
以及在不同方案下,大概需要的内存空间和计算时间。也就是估算时间 和 空间 。比如:
|
||||
|
||||
```
|
||||
8位的电话号码,最多有99 999 999个
|
||||
IP地址
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 分而治之/Hash映射
|
||||
|
||||
这里的`Hash映射`是指通过一种映射散列的方式,将数据均匀分布在对应的内存或更小的文件中
|
||||
这里的`Hash映射`是指通过一种映射散列的方式,将海量数据均匀分布在对应的内存或更小的文件中
|
||||
|
||||
使用hash映射有个最重要的特点是: `hash值相同的两个串不一定一样,但是两个一样的字符串hash值一定相等`
|
||||
使用hash映射有个最重要的特点是: `hash值相同的两个串不一定一样,但是两个一样的字符串hash值一定相等`。哈希函数如下:
|
||||
|
||||
```
|
||||
int hash = 0;
|
||||
for (int i=0;i<s.length();i++){
|
||||
hash = (R*hash +s.charAt(i)%M);
|
||||
}
|
||||
```
|
||||
|
||||
大文件映射成多个小文件。具体操作是,比如要拆分到100(M)个文件:
|
||||
|
||||
@@ -56,9 +64,7 @@ IP地址
|
||||
|
||||
比如,某文件中有若干8位数字的电话号码,要求统计一共有多少个不同的电话号码?
|
||||
|
||||
分析:8位最多99 999 999 , 如果1Byte表示1个号码,需要95MB空间,但是如果1bit表示1个号码,则只需要 95/8=12MB 的空间。
|
||||
|
||||
这时,数字k(0~99 999 999)与bit位的对应关系是:
|
||||
分析:8位最多99 999 999, 如果1Byte表示1个号码,需要95MB空间,但是如果1bit表示1个号码,则只需要 95/8=12MB 的空间。这时,数字k(0~99 999 999)与bit位的对应关系是:
|
||||
|
||||
```
|
||||
#define SIZE 15*1024*1024
|
||||
@@ -98,52 +104,122 @@ Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速
|
||||
|
||||
##### Bloom filter 算法
|
||||
|
||||
Bloom filter可以看做是对bitmap的扩展。
|
||||
Bloom filter可以看做是对bitmap的扩展。只是使用多个hash映射函数,从而减低hash发生冲突的概率。算法如下』
|
||||
|
||||
1. 创建 m 位的bitset,初始化为0, 选中k个不同的哈希函数
|
||||
2. 第 i 个hash 函数对字符串str 哈希的结果记为 h(i,str) ,范围是(0,m-1)
|
||||
3. 将字符串记录到bitset的过程:对于一个字符串str,分别记录h(1,str),h(2,str)...,h(k,str)。 然后将bitset的h(1,str),h(2,str)...,h(k,str)位置1。也就是将一个str映射到bitset的 k 个二进制位。
|
||||
|
||||
4. 检查字符串是否存在:对于字符串str,分别计算h(1,str)、h(2,str),...,h(k,str)。然后检查BitSet的第h(1,str)、h(2,str),...,h(k,str) 位是否为1,若其中任何一位不为1则可以判定str一定没有被记录过。若全部位都是1,则“认为”字符串str存在。
|
||||
|
||||
但是若一个字符串对应的Bit全为1,实际上是不能100%的肯定该字符串被Bloom Filter记录过的。(因为有可能该字符串的所有位都刚好是被其他字符串所对应)这种将该字符串划分错的情况,称为false positive 。
|
||||
|
||||
5. 删除字符串:字符串加入了就被不能删除了,因为删除会影响到其他字符串。实在需要删除字符串的可以使用Counting bloomfilter(CBF)。
|
||||
|
||||
|
||||
实现示例:
|
||||
`Bloom Filter使用了k个哈希函数,每个字符串跟k个bit对应。从而降低了冲突的概率。`
|
||||
|
||||
|
||||
|
||||
##### 最优的哈希函数个数
|
||||
|
||||
哈希函数的选择对性能的影响应该是很大的,一个好的哈希函数要能近似等概率的将字符串映射到各个Bit。选择k个不同的哈希函数比较麻烦,一种简单的方法是选择一个哈希函数,然后送入k个不同的参数。
|
||||
|
||||
|
||||
##### 错误率估计
|
||||
|
||||
|
||||
|
||||
##### 位数组的大小
|
||||
|
||||
|
||||
|
||||
|
||||
##### 实现示例
|
||||
|
||||
```
|
||||
#define SIZE 15*1024*1024
|
||||
char a[SIZE]; /* 15MB*8 = 120M bit空间 */
|
||||
memset(a,0,SIZE);
|
||||
|
||||
int seeds[] = { 5, 7, 11, 13, 31, 37, 61};
|
||||
|
||||
int hashcode(int cap,int seed, string key){
|
||||
int hash = 0;
|
||||
for (int i=0;i<key.length();i++){
|
||||
hash = (seed*hash +key.charAt(i));
|
||||
}
|
||||
return hash & (cap-1);
|
||||
}
|
||||
```
|
||||
|
||||
对每个字符串str求哈希就可以使用 `hashcode(SIZE*8,seeds[i],str)` ,i的取值范围就是 (0,k)。
|
||||
|
||||
|
||||
##### Bloom filter应用
|
||||
|
||||
* 拼写检查
|
||||
* 拼写检查一类的字典应用
|
||||
* 数据库系统
|
||||
* 网络领域
|
||||
* 网络领域(爬虫,web cache sharing)
|
||||
|
||||
|
||||
参考:http://www.cnblogs.com/heaad/archive/2011/01/02/1924195.html
|
||||
##### 参考
|
||||
http://www.cnblogs.com/heaad/archive/2011/01/02/1924195.html
|
||||
http://blog.csdn.net/jiaomeng/article/details/1495500
|
||||
http://pages.cs.wisc.edu/~cao/papers/summary-cache/node8.html `哈希函数个数k、位数组大小m` 测试论证
|
||||
|
||||
|
||||
### Trie树
|
||||
|
||||
|
||||
|
||||
|
||||
### 数据库索引
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### 倒排索引(Inverted index)
|
||||
|
||||
也叫反向索引。是文档检索系统中最常用的数据结构。
|
||||
|
||||
常规的索引是文档到关键词的映射,如果对应的文档是
|
||||
|
||||
|
||||
|
||||
[Elasticsearch](https://github.com/elastic/elasticsearch)就是使用倒排索引(inverted index)的结构来做快速的全文搜索。ElasticSearch 不仅用于全文搜索, 还有非常强大的统计功能 (facets)。
|
||||
|
||||
携程,58,美团的分享中都提到ES构建实时日志系统,帮助定位系统问题。
|
||||
|
||||
|
||||
http://es.xiaoleilu.com/index.html
|
||||
|
||||
### 双层桶划分
|
||||
|
||||
|
||||
|
||||
|
||||
### 外排序
|
||||
|
||||
|
||||
|
||||
### 分布处理之Mapreduce
|
||||
|
||||
|
||||
|
||||
### Hadoop
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user