索引压缩
为什么要压缩?
- 增加内存存储内容, 增加高速缓存(caching)技术的利用率(加快速度)
- 加快从磁盘到内存的数据传输速度 (同样加快速度)。(读压缩数据到内存+在内存中解压)比直接读入未压缩数据要快很多。(前提: 解压速度要很快)
- 减少磁盘空间 (节省开销)
词典压缩:
词典压缩的主要动机: 使之能够尽量放入内存中
倒排记录表压缩:
倒排记录表压缩的主要动机: 减少磁盘存储空间,减少从磁盘读入内存的时间
注意: 大型搜索引擎将相当比例的倒排记录表都放入内存
有损(Lossy) vs 无损(Lossless)压缩
有损压缩: 丢弃一些信息。前面讲到的很多常用的预处理步骤可以看成是有损压缩:统一小写,去除停用词, Porter词干还原, 去掉数字
无损压缩: 所有信息都保留。索引压缩中通常都使用无损压缩
信息检索中词项的统计特性
词项数目(即词汇表(词典) 大小)的估计:Heaps定律 M = kTb
M 是词汇表大小, T 是文档集的大小(文档集合中所有词条的个数,即所有文档大小之和)
参数k 和b 的一个经典取值是: 30 ≤ k ≤ 100 及 b ≈ 0.5.
Heaps定律通过文档集合中的词条数来估计词汇表大小,词汇表大小会随着文档集的大小增长而增长!
Heaps定律结论:
- 随着文档数目的增加,词汇量会持续增长而不会稳定到一个最大值。
- 大规模文档集的词汇量也会非常大。
词项分布的估计:Zipf定律 cfi ∝ (1/i)
如果出现最多的词项的出现次数是 cf1的话,出现第二多的词项的出现次数就是 cf1的一半,出现第三多的词项出现次数会是 cf1的 1/3,其余均可依此类推。
注:cfi 是文档频率(collection frequency): 词项ti在所有文档中出现的次数(不是出现该词项的文档数目df)
词典压缩
根据Heaps定律,词典会随着文档集的增加而持续增长,因此为了能够把词典全部都放在内存中,我们必须要对其进行压缩。
回顾: 定长数组方式下的词典存储
需要空间:词项+文档频率+倒排记录表指针(20+4+4)*M
大量存储空间被浪费(英语中每个词项的平均长度为8个字符),即使是长度为1的词项,我们也分配20个字节。
不能处理长度大于20字节的词项。
定长数组方式进行优化:将所有的词项存成一个长字符串并给每个词项增加一个定位指针,它在指向下一词项的指针同时也标识着当前词项的结束。
需要空间:词项+文档频率+倒排记录表指针+指向字符串的指针(8+4+4+3)*M
进一步压缩:将长字符串中的词项进行分组变成大小为k 的块(即 k 个词项一组) ,然后对每个块只保留第一个词项的指针。同时,我们用一个额外字节将每个词项的长度存储在每个词项的首部。
再进一步压缩:回顾词典是按字母排序的,词项之间的冗余性信息还没有利用,实际上,按照词典顺序排序的连续词项之间往往具有公共前缀。
前端编码(Front coding):当某个词和前一个词有共同的前缀的时候,后面的词仅仅保存前缀在词中的偏移(offset),以及除前缀以外的字符串(称为后缀)。
8automata8automate9automatic10automation可以采用前端编码方式继续压缩为8automat*a1◇e2◇ic3◇ion
多个连续词项具有公共前缀 automat,那么在前缀的末尾用“ *” 号标识,在后续的词项中用“◇” 表示该前缀。和前面一样,每个词项的前面第一个字节存储了该词项的长度
倒排记录表压缩
对间隔编码: 存储docID间隔而不是docID本身
可变字节(VB)码
- 变长的整数类型,它可能包含多个Byte,对于每个Byte的8位,其中后7位表示数值,最高1位表示是否还有另一个Byte,0表示没有,1表示有。
- 越前面的Byte表示数值的低位,越后面的Byte表示数值的高位。
- 例如130化为二进制为 1000, 0010,总共需要8位,一个Byte表示不了,因而需要两个Byte来表示,第一个Byte表示后7位,并且在最高位置1来表示后面还有一个Byte,所以为(1) 0000010,第二个Byte表示第8位,并且最高位置0来表示后面没有其他的Byte了,所以为(0) 0000001。
一元编码
如果为数n,则n个1后面添一个0。例如3→ 1110
Elias gamma编码
Wiki地址:http://en.wikipedia.org/wiki/Elias_gamma_coding
- 将G 表示成长度(length)和偏移(offset)两部分
- 偏移对应G的二进制编码,只不过将首部的1去掉。例如 13 → 1101 → 101 = 偏移
- 长度部分给出的是偏移的位数。比如G=13 (偏移为 101), 长度部分为 3。长度部分采用一元编码: 1110.
- 于是G的Elias gamma编码就是将长度部分和偏移部分两者联接起来得到的结果。13→1110,101
Elias delta编码
Wki地址:http://en.wikipedia.org/wiki/Elias_delta_coding
对于大数字来说,γ 编码的效率相对较低,这是因为在对偏移部分长度进行编码的时候采用了效率并不高的一元编码,在这点上,δ 编码和 γ编码不一样,即偏移长度部分进行编码并不采用一元编码,而是采用 γ 编码。
例如13的长度部分采用γ 编码为101,13→101,101
注:δ 编码和 γ编码有等价编码方法,估最后编码结果可能会有所不同