首页 > 代码库 > 倒排表压缩算法
倒排表压缩算法
倒排表内存放的都是整型数字,所以对倒排表的压缩其实就是对数字的压缩。而二进制数字都是存储在long(8byte) ,int(4byte),short(2byte)类型里面,这种存储方式最大的弊端就是每个数字不管大小消耗的空间都是等价的,比如int的1和int的100000000都是4个字节,而数字1其实仅仅用到了一个字节,其他3个字节的空间纯属浪费。倒排表压缩的核心思路就是在这些没用到的字节上做文章。
整型压缩分为两种方式,一种是以byte为最小单位压缩,一种是以bit为最小单位压缩。
基于byte的压缩
vint压缩
这种算法每个数字所占用的空间都是变长的,尽量接近数字本身的有效字节数。那么就会有个明显的问题,因为是变长,如何记入每个数字的长度?vint的解决方式是用每个字节的最高位来表示这个数字是否还有后续字节
比如数字386,二进制是下面这样的,有效字节2个
00000000 00000000 00000001 10000010
如果按照vint压缩已经就是这样了,红色标记的1不是有效数据位,而是代表数字在当前这个字节后面还有数字,而原来在最高位的那个1就被推到第二个字节的第一位上面去了。由于386这个数字本来只有2个有效字节,所以第二个字节的最高位就是0,表示无后续字节了。
00000011 10000010
lucene就是采用这样的压缩方式,具体实现我另外一篇blog有介绍
simple-9压缩
这种方式比较好理解,就是把一个32位的int类型分成2个区域,前4个字节表示这个int内存储数字的个数(表示为n),后面28位用来放多个数值,每个数值所占的位数都是等分的,等于28/n,之所以是simple-9是因为前4个字节表示9种状态,列表如下
状态位(前4bit) 存放数据位(后28bit)
1 表示存放1个数字,每个长度为28bit
2 表示存放2个数字,每个长度为14bit
3 表示存放3个数字,每个长度为9bit
4 表示存放4个数字,每个长度为7bit
5 表示存放5个数字,每个长度为5bit
6 表示存放7个数字,每个长度为4bit
7 表示存放9个数字,每个长度为3bit
8 表示存放14个数字,每个长度为2bit
9 表示存放28个数字,每个长度为1bit
基于bit的压缩
γ压缩
这种算法把数字压缩以后分成3段,以此表示 有效位长度-分隔符号-有效位数据
还以 386这个数字为例
原始的二进制情况是下面这样
00000000 00000000 00000001 10000010
有效位是 1 10000010,位数为9,但是因为任何一个数字有效位的最高位都是1(废话),所以其实压缩的时候不需要存放最高位那个1,只要在解压的时候在有效位的最前面在加个1就可以了,所以其实需要存储的有效位数为8。
因此按照γ压缩后就变成这样了,红0是分隔符,红0后面位代表386去掉最高位的1以后的有效位,而有效位的长度等于0前面连续1的个数
11111111010000010
差值存储
倒排表压缩算法