SlideShare une entreprise Scribd logo
1  sur  18
整型数据(byte int long)编码性能的综合测试报告
技术报告
中国科学院计算技术研究所先进计算机系统实验室系统结构组
王猛
2014.03.20
摘 要
本文主要是整型数据的所采用的各种基本编码及其组合编码方式进行了理论分析,指出
每种编码适合的分布类型和优缺点,并采用多组实验进行分析说明,指出了对这些编码进行
改进和重组的一些想法,以及关于编码的一点展望。
1. 调研编码的动机
对于保存在 hdfs 文件系统上的数据而言,优秀的编码方式主要有以下有点:减小磁盘
存储空间,减少 sql 查询从磁盘读取的数据量即磁盘 IO,从而提高查询效率。一个优秀的编
码方式主要是结合数据类编码数据的类型及其 value 的分布情况,如:随机分布,重复值很
多且不连续的分布,重复值较多且连续的分布,等差数列分布,相邻数值增量差很小的分布,
值随机分布但总的个数较少的分布。每一种分布情况都有一种最适合它的编码算法。而如何
统计出值的分布情况则是一个关键点。一般而言,评价一个编码性能好坏最直观的标准是:
压缩比,编码时间,解码时间。结合 Hive 的实际情况,一般而言,对于数据,我们进行的
更多的操作是查询,所以说解码的时间要求更为高一些。通常可以这么认为,在压缩比差别
不是很大的情况下,尽量选择解码时间短的编码方式。当然这只是一般情况。还有很多结合
具体应用的情况,比如说,有些列的数据就很少会被查询到,这样子的话,压缩比当然是首
要因素了。
2. 基本编码方式的分析
2.1. Parquet 部分的整型编码:
Parquet 的整数编码主要分为 plain Encoding ,Dictionary Encoding,Delta Encoding,
bit-packing Enconding 和 Run Length Encoding 基本编码。
2.1.1. Plain Encoding
最简单编码。即按照 value 出现的顺序依次进行存储,唯一需要注意的是,在存储值的
时候采用的是 little endian,对于像 Int 这样由多个字节组成的数值类型,其采用的是先存储
低位字节,然后存储高位字节。原因是发现通过对 Integer.reverseBytes(in.readInt())和 keep a
member byte[4], wrapped by an IntBuffer with appropriate endianness set and call IntBuffer.get()
这两个方法的测试,小端存储比大端存储更快。
2.1.1.1 优缺点以及适合场景
优点:最普通的编码,基本无。
中国科学院计算技术研究所先进计算机系统实验室
2
缺点:实际上没有起到任何节省空间的效果。
适合场景:在其他编码均不能起作用的情况下
2.1.2. Dictionary Encoding
字典编码主要由字典中的字典值以及存储 value 的字典项编号组成。比如:现在字典是
5(1),8(2),10(3) 其字典值是 5,8,10.对应的字典编号是 1,2,3.现在需要存储数值 5,8,5,10,8.
那么存储的顺序值就是其 id 号,即 12132.
2.1.2.1 优缺点以及适合场景
优点:对于非重复值很少的情况特别适合,其中 byte 型由于最多去 256 个 value,可以
认为随机分布的 byte 在压缩比这一块最适合的是字典编码。
缺点:字典编码的 size 由字典 size 和字典项 ID 的 size 两部分,对每一个 value 进行编
码和解码都需要和字典和字典项 ID 打交道,这是其在实际场景中编码解码都很耗时的原因
之一。字典编码的效果主要受限于非重复值的个数及其分布情况,以及字典编码的粒度,实
验中发现字典编码在某些情况下会出现比原始数据还大的最差情况。
适合场景:byte 型,非重复值很少
2.1.3. Bit-packing Encoding
举例来说明,现在需要存储 java int 类型的 0,1,2,3,4,5,6,7 这 8 个值,在不做任何处理
的情况下需要占用的大小是 4*8 即 32 个字节,32*8 个位。现在采用位编码来存储这些数据:
存储规则是计算需要存储的值中的在最大值的实际占用的有效位。比如上述值中的最大值是
7,其具体存储是 00000000 00000000 00000000 00000111
则其有效位是 111,我们只需要用三个 bit 就可以存储所有比此最大值小的值,所以采用如
下的位编码进行存储,占用的存储空间是 3*8=24 bit,大大节省了存储空间:
十进制数: 0 1 2 3 4 5 6 7
bit 值: 000 001 010 011 100 101 110 111
bit 标签: ABC DEF GHI JKL MNO PQR STU VWX
编码之后如下所示:
bit 值: 00000101 00111001 01110111
bit 标签: ABCDEFGH IJKLMNOP QRSTUVWX
2.1.3.1 优缺点以及适合场景
优点:采用有效 2 进制的位数来编码,节省了存储空间。此编码的性能不仅取决于值的
分布情况,还取决于
缺点:节省空间的效果受限于编码基本单元中最大值的有效 2 进制位数,如果值都是很
大的情况下,编码效果不明显。
适合场景:值的有效 2 进制位数较少的情况。
2.1.4. Run Length Encoding
此编码对于连续多次出现的重复编码很有效,这里的 RLE 编码和郭师兄的 RLE 的主要
整型数据(byte int long)编码性能的综合测试报告
3
区别是,其内部使用了前面提到的位编码来存储值和值出现的次序。比如 111222(假设每
个值用一个字节表示,则一共 6 个字节),即 1 3 2 3 。则存储是: 00000001 00000011
00000010 00000011 需要 4 个字节。如果采用位编码的话,则存储是:01 11 10 11 一共 8
个位即可以表达。
2.1.4.1 优缺点以及适合场景
优点:结合了位编码的 RLE 适合于连续出现的重复值较多的情况的编码。
缺点:parquet 的 RLE 编码只能针对重复出现的 value 进行编码,不能对等差数列进行
编码。
适合场景:连续出现重复值
2.1.5. Delta bit -packing Encoding
即增量编码和位编码混合编码。以 7,5,3,1,2,3,4,5 为例:先计算出两个相邻的值的增量,
分别为 -2 -2 -2 1 1 1 1 ,在计算的同时保存最小的增量值,这里是-2.需要注意的是最小的
增量值-2 使用 zigzag VLQ int(此时-2 变为 3)类型来保存的。接下来对-2 -2 -2 1 1 1 1 分别
减去最小的增量值-2,则变为 0,0,0,3,3,3,3 ,最大值 3 的二进制代码为 0000000 0000000
0000000 000000011 有效编码是 11 两位,那么就使用 2 个 bit 来保存所有的增量差, 所以这
里用一个 byte 来保存 width 2.对这个序列采用位编码。即依次为 00 00 00 11 11 11 11 。增量
编码保存值的顺序为:first value(7 zigzag VLQ int 变为 14) minimum delta(- 2 zigzag
VLQ int 变为 3) bitwidth(2 1byte) bitcode(00 00 00 11 11 11 11) .所以 7,5,3,1,2,3,4,5 的增
量编码为:00001110(14) 00000011(3) 00000010(2) 00000011 111111 共计花费
8+8+8+14=38 位,比原先的 32*8=256 位减少很多。
在这里简要说一下 ZigZag VLQ int,这种编码风格源自于 google protobuffer, zigzag 主要
是应对针对负数的编码,该编码会将有符号整型映射为无符号整型,以便绝对值较小的负数
仍然可以有较小的 varint 编码值,如-1.下面是 ZigZag 对照表:
Signed Original Encoded As
0 0
-1 1
1 2
-2 3
2147483647 4294967294
-2147483648 4294967295
其公式为:
(n << 1) ^ (n >> 31) //sint32
(n << 1> ^ (n >> 63) //sint64
需要补充说明的是,Protocol Buffer 在实现上述位移操作时均采用的算术位移,
因此对于(n >> 31)和(n >> 63)而言,如果 n 为负值位移后的结果就是-1,否则就是 0。
2.1.5.1 优缺点以及适合场景
优点:此种编码是在值随机分布情况中综合性能最好的,它不要求你的值是连续重复或
者是等差数列,也不受限于数据的有效 2 进制位的个数,仅仅希望相邻数值的增量差小点就
中国科学院计算技术研究所先进计算机系统实验室
4
行。此编码的性能除了收到相邻数据的增量的差的大小的影响,还受到一个人为设定的基本
粒度的大小的影响,应为其采用的位编码的 2 进制位的个数取决于基本编码粒度中最大的增
量差的有效 2 进制位数。
缺点:如果相邻数值的增量差波动很大,那么编码效果有限
适合场景:相邻 value 增量差较小
2.2. ORC 的整型编码调研
2.2.1. 位编码
位编码适合于用来存储 NULL 值,如果值为 NULL,则用 bit 0 表示,否则用 bit 1 表示
不为 NULL(此时需结合其他编码)。
2.2.2. RLE 编码
对于 int,long,short 类型的字段,使用 RLE 编码。该编码能够对等差数列(完全相等也
属于等差数列)进行压缩,该等差数列需要满足以下两个条件:
1.至少有含3个元素满足等差数列
2.差值在-128~127之间(因为差值用1Byte 来表示)
Run-Length 的具体存储如下:
第一个 Byte 是 Control Byte,取值在-128~127之间,其中-1~-128代表后面存储着
1~128个不满足等差数列的数字,0~127代表后面存储着3~130个满足等差数列的数字;
如果 Control Byte>=0,则后面跟着一个 Byte 存储等差数列的差值,否则跟着-Control
Byte 这个负数。
如果 Control Byte>=0,则继差值之后跟着等差数列的第一个数。
例子:
原始数字:12,12,12,12,12,10,7,13
经过 Run-Length 的数字:2, 0,12,-3,10,7,13
绿色代表 Control Byte,蓝色代表差值,黑色代表具体的数字。
细节提示,在 RLE 编码中,可以用一个 byte 来存储控制位,一个 byte 来存储数列的差
值,这样可以节省存储空间,毕竟实际情况几乎没有长度到达2的31次方的等差数列,也没
有差值达到2的31次方的等差数列。
2.1.4.1 优缺点以及适合场景
优点:除了可以对连续出现的重复值进行编码外,也可以对等差数列进行编码
整型数据(byte int long)编码性能的综合测试报告
5
缺点:和 parquet 相比,没有利用位编码进一步节省空间
适合场景:连续出现重复值或者等差数列较多
2.2.3. Variable-width Encoding
基于 Google's protocol buffers ,是使用一个或多个字节表示整型数据的方法(字节是此
编码的基本单元)。其中数值本身越小,其所占用的字节数越少. 在 varint 中,每个字节中
都包含一个 msb(most significant bit)设置(使用最高位),这意味着其后的字节是否和当前字
节一起来表示同一个整型数值。而字节中的其余七位将用于存储数据本身。如果高位是 1
则表示后面还有字节来表示同一个整数值,如果高位是 0 则表示此字节是此数的最后一个字
节。通常而言,整数数值都是由字节表示,其中每个字节为 8 位,即 Base 256。然而在 Protocol
Buffer 的编码中,最高位成为了 msb,只有后面的 7 位存储实际的数据,因此我们称其为
Base 128(2 的 7 次方)。考虑到此高位的值的含义已经取代了符号位的含义,那么对于负数
的编码,需要先使用 zigzag 编码把负数映射为非负数。这种编码对于小的值的存储比较有
效果。
由于 Protocol Buffer 是按照 Little Endian 的方式进行数据布局的,因此我们这里需要将
两个字节的位置进行翻转
比如数字 1,它本身只占用一个字节即可表示,所以它的 msb 为其本身的值,如:
0000 0001
再比如十进制数字 300,它的编码后表示形式为:
1010 1100 0000 0010
对于Protocol Buffer 而言又是如何将上面的字节布局还原成300呢?这里我们需要做的
第一步是 drop 掉每个字节的 msb。从上例中可以看出第一个字节(1010 1100)的 msb(最
高位)被设置为 1,这说明后面的字节将连同该字节表示同一个数值,而第二个字节(0000
0010)的 msb 为 0,因此该字节将为表示该数值的最后一个字节了,后面如果还有其他的字
节数据,将表示其他的数据。
1010 1100 0000 0010
-> 010 1100 000 0010
上例中的第二行已经将第一行中每一个字节的 msb 去除。由于 Protocol Buffer 是按照
Little Endian 的方式进行数据布局的,因此我们这里需要将两个字节的位置进行翻转。
010 1100 000 0010
-> 000 0010 010 1100 //翻转第一行的两个字节
-> 100101100 //将翻转后的两个字节直接连接并去除高位 0
-> 256 + 32 + 8 + 4 = 300 //将上一行的二进制数据换算成十进制,其值为 300.
上面的举例是反编码,下面举例如何编码为 Protocol Buffer.
先表示具体值----从低位开始以 7 为模划分,不足的补为 0----翻转数据(小端存储)
-----添加 msb 值 0 OR 1.
比如 java int 137 ,其不做编码的二进制表示为 0000000 00000000 00000000
10001001 需要 4 个字节,有效位是 10001001,对其进行处理:
中国科学院计算技术研究所先进计算机系统实验室
6
1. 7 bit 一组,把二进制分开,不足的补 0 ,变成 0000001 0001001
翻转数据,0001001 0000001
2. 把最低的 7 位拿出来,在最高位补 0 表示最后一位,变成 00000001,这个作为最低
位,放在最后边。
3. 在其他组的最高位补 1 ,表示没有结束,后面跟着还有数据。在这里就是 10001001
4. 拼在一起,就变成了 10001001 00000001 只需要两个字节就可以存储。
3. 组合编码
第 2 部分里面我们对一些基本编码进行了较为详细的分析,每一种基本编码的适合场景
条件限制很多,所以需要结合相关特点进行组合。实际情况下把上述各种编码组合起来的效
果更加,我们主要分为 3 类符复合编码。
编
码来源
编
码方式
优点 缺点 典
型应用
是否发现
改进点
Parquet Delta
bit packing
Encoding
充分结合了增量编码和
位编码的优势,增量编码对于那
种不重复出现的随机分布的数
值进行编码最合适不过了。鉴于
是对 int 序列的相对增量进行
编码,所以一般就不会受 int 值
本身大小的影响,一般不会存在
前面位编码受较大值的影响的
情况。此处需要规避负数的位编
码问题,如果序列的增量出现了
负数,则需要以序列的增量中的
最小负数为基准,为每一个增量
值加上此最小负数的绝对值
对于连续多次出现重复值的情况,可能
性 能 不 及 RLE 编 码 。 对 于
11111111112222222222 这样的序列:RLE 编
码为:1 10 2 10 代价为 4 个字节(如果 RLE
内部还使用 bit-packing 的话就更小了)。
Delta bit packing Encoding 编码则会
偏大,究其原因是此编码不能很好利用重复值
情况,即使 delta 是 0,那么得用一个 zigzag VLQ
INT 来保存 0,一个 byte 来保存 0,然后每两个
相邻值的差值还得用一个 bit 0 存储。
特 别
适合于值分
布随机无明
显规律的情
况,但是最
好是相邻两
个值的增量
不要过大,
不然会影响
位编码的性
能
合理的确定
一个长度的数组作
为基本单元,此基
本单元的所有数值
的 bit 长度取决于
此数组对负增量修
正 后 的 最大 增 量
值 , 所 以要 确 保
delta 不要过大。还
有就是是否可以让
此编码增加对连续
重复值的支持。
组 合
Parquet
Dicti
onary
Encoding
+bit-packing
Enconding+
Run Length
总体上采用字典编码,内
部依据字典项 id 连续出现的情
况采用 RLE-Bit Packing (连续
出 现 重 复 次 数 多 ) 或 者 bit
packing 编码(值分布随机)
考虑到此处的位编码是
用于对字典项 Id 进行编码,id
当然是非负数,规避了负数的位
编码问题)
关于界定何时使用单纯的位编码还是使
用 RLE 和位编码的混合编码。以及是否可以考
虑在字典内部也采用位编码保存,而不仅仅是
对字典项 id 使用位编码
适 合
于重复值较
多 的 情 况
(不论是否
连续出现),
不适合值分
布随机的情
况
字典内部是否可以
支持位编码,或者
说是字典内部对值
的保存采用
Google's
protocolbuffers 的
variable-width
ORC RLE 相比于 parquet 中的只能
对重复值进行编码的 RLE 的情
况,增加了对等差数列的编码支
持。适合于等差序列的值的编
码,即使出现的值是随机分布
的,也仅需要一个 byte 大小的
控制位的额外存储。
未能考虑对存储的value的有效位进行编
码。
重 复
值较多或等
差数列较多
内部可以嵌
入位编码
4. 测试报告
4.1. 测试说明
此次测试涉及到的编码是可靠且正确的,对于编码和解码的时间,也是通过对源码细节
的理解,卡的比较精确。对于 int 类型而言,总大小为 382M,以 10M 为粒度进行测试,总
共执行 39 次的编码和解码操作。对于 byte 类型而言,总大小为 382M,以 2.5M 为粒度进行
测试,总共执行 153 次的编码和解码操作。
整型数据(byte int long)编码性能的综合测试报告
7
测试遵循单一变量原则,可以认为此次测试有一定的代表性。
4.2. 测试环境
内存 磁盘空间 cpu OS Linux 内核
4G 900G 1 cpu X 4
cores
Centos 6.2 2.6.32
4.3. 测试数据类型和分布情况
来源 类型 大小 有序 值分布情况
tpch-lineite
m:l_orderkey
int 382M 是 有序且有较少数目的重复值,相邻数值增量
差较小 1161273537 1161273538 1161273538
1161273538 1161273538 1161273539
1161273539 1161273539 1161273539
1161273540 1161273540
tpch-lineite
m:l_partkey
int 382M 否 随机分布,相邻数据的增量较大且无规律
如 : 12121910 3173943 24450539
20206290 7113357 34190843 5490008
30561624 9208575 8517641 35984160
25763416 5729027 21656575 22047084
9951961 22600207 7801511
tpch-lineite
m:l_partkey(sort)
int 382M 是 排序之后重复值出现在一起,相邻数据的
差值较小
tpch-lineite
m:l_linenumber
int 382M 否 相邻数值增量很小,且存在等差数列,取
值个数也很少
3 4 5 6 7 1 2 3 4 5 6 1 2 3 1 2 3 4 5 6 1 2 3 4
5 6 7 1 1 1 2 3 4 5 1 2 1 2 3 4
tpch-lineite
m:l_linenumber(so
rt)
int 382M 是 排序之后出现很长很长的重复值串
tpch-lineite
m:l_returnfalg
byte 382M 否 取值局限于 78,82,65 三个值,且存在一定
的连续重复情况,如:78 82 82 65 65 65 82 82 78
78 78 78 78 82 65 65 82 78 65 78 78 78 78 78
tpch-lineite
m:l_returnfalg(sort
)
byte 382M 是 排序之后出现很长很长的重复值串
tpch-lineite
m:l_linestatus
byte 382M 否 虽然无序,但取值局限于 2 个值:79,70,且
出现较长的连续重复串 如:79 79 79 79 79 79 70
70 70 79 79 797979 79 79 79 79 70 70 70 70
tpch-lineite
m:l_linestatus(sort)
byte 382M 是 排序之后出现很长很长的重复值串
tpc-ds-
promotion :
p_channel-tv
byte 382M 否 随机分布,无明显规律
tpc-ds-
promotion :
p_channel-tv(sort)
byte 382M 是 排序之后,呈现大片的连续重复的 value
4.4. 测试结果说明
4.4.1. L_orderkey(默认有序)
中国科学院计算技术研究所先进计算机系统实验室
8
图 1 l_orderkey 压缩比
图 2 l_orderkey 编码解码时间
4.4.1.1 分析
1)Parquet 的 deltabianryPackinZigzar 编码优势明显,主要在于默认有序的 l_orderkey
相邻数值的增量差比较小;
2)Orc 的 RLE 也有 0.47 的压缩率,一是在于默认有序的了——orderkey 有一定的连续
出 现 的 重 复 值 和 等 差 数 列 , 至 于 此 RLE 的 编 码 和 解 码 时 间 较 Parquet 的
0.18
0.88
0.47
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE
压缩比
压缩方式
l_orderkey(int)
2.57
23.838
4.537
1.978
5.199
3.339
0
5
10
15
20
25
30
Parquet.DeltaBinaryParquet.DictionaryRleBit ORC.RLE
编码解码时间(s)
压缩方式
l_orderkey(int)
编码时间
解码时间
整型数据(byte int long)编码性能的综合测试报告
9
deltabianryPackinZigzar 长,主要则在于后者运用到了一些更适合机器的位运算;
3)在此组测试中,发现 parquet 的字典编码 dictionaryRleBitPackingVlq 性能很差,就编
码时间的而言其比另外两种编码慢很多,一是因为在字典编码中保存字典项 ID 的编码中,
采用了一个重复值 count 计数器,当连续出现的重复值达到 8 以上的时候采用 RLE 编码,
否则采用位编码。这么做的目的当然是为了获得更好的压缩比,但是针对 id 的判断会大大
增加编码的时间;而编码慢的另外一个原因是编码的时候需要先从字典中获取此 value 的 id,
然后再把此 id 进行 RLE 和 bitpacking 混合编码,相当于对一个 value 编码需要量进行 2 步。
这也是其慢的一个重要原因。而字典编码的解码时间慢则主要在于每次获取一个值的时候除
了需要先对字典项 id 进行解码获得 id 值,然后再依据此 id 从字典中查询相对应的值,也是
需要 2 步才能获得原始 value.
而对于字典编码的编码效果不理想,则分为两点:字典和字典项的问题。在保存字典的
时候,没有采用任何编码对字典进行压缩,在这里个人介意用 deltabitpacking 编码会较大的
减小字典的 size。而就字典 ID 编码而言,其采用的位编码的 size 取决于字典的 size 的有效
二进制位,这样不如 deltabitpacking 起到的压缩效果好。但是,前面已经说过,对字典不做
任何编码的情况下,编码时间本来就很长,此时再添加新的增量编码岂不是会变的更慢?!
如果在字典编码中添加了 deltabitpacking 编码,那么这种字典编码和我们那个只有
deltabianrypackingZigzar 的编码的优势在哪里?是在于对重复值的保存上免去了对重复值的
保存,但是不要忘了我们在用字典编码保存一个值的时候,其实际代价来自于字典和字典项
ID 两个存储代价。
4)需要说明的是,上一次我提交的测试报告中是对 1 亿行数据进行一次整体编码的,
而这一次则是对 int 以 10M 为单位编码,测试结果发现。编码粒度的大小对 parquet 的
deltabinaryPackingZigzar 编码和 ORC 的 RLE 编码几乎没有影响,这也是可以解释的,因为
对于 deltabinaryPackingZigzar 编码而言,我们在编码过程中会选 128byte 大小左右的 size 为
基本增量编码的粒度,这个粒度的选择才是增量的关键,而与外面这个 10M 或者是 382M
的大的粒度没有关系;就 ORC 的 RLE 而言,其编码效果受限与连续数值的分布情况,也和
外面这个 10M 或者是 382M 的大的粒度没有关系;
偏偏就 parquet 的 DictinoaryRleBitPackingVlq 编码受粒度影响很严重。2 组测试显示,
对于 l_orderkey 而言,382M 的粒度的字典总 size 是 99M,字典 ID 是 299M,而 10M 粒度
的字典总 size 也是 99M,字典 ID 是 238M,多了 61M。解释原因如下:由于 l_orderkey 默
认有序,所以重复的字典值是连续重现的,这样的话无论粒度怎么划分,连续出现的某个值
一般是落在同一个粒度块的,这就使得总的字典 size 基本没什么变化,但是为何字典 ID 编
码差距这么大呢?主要在于对于字典项 ID 编码所采用的位编码所致,我们知道采用位编码
的话需要选取一个用来进行位编码的长度。在这里,此长度是由字典的 size 来决定,位宽
bitwidth=字典 size 的有效二进制位的长度。很显然,把 382M 的数据都放在一个字典里的字
典 size 肯定远远大于存放 10M 的数据的字典的 size,所以 10M 这种小粒度的 bitwidth 远远
小于 382M 的位宽,这就导致小粒度 10M 的字典 ID 的编码效果远远好于 382M 的大粒度。
这是对于有序数据而言小粒度和大粒度的差别,下面谈谈无需的时候,小粒度和大粒度的差
别:
和前面分析一样,deltabinaryPackingZigzar 和 ORC.RLE 在无序情况下不受粒度大小的
影响。通过对无序的 l_partkey 的测试显示,382M 粒度的字典大小为 141M,字典项 ID 的
大小为 311M,而 10M 粒度的字典总大小为 370M,字典 ID 为 261M,对于小粒度的字典项
ID 小于大粒度的字典项 ID 的原因上面已经说了,这里解释字典 size.对于无序的数据而言,
有可能有 10 个值为 100 的数据分布在 10 个粒度里面,这样的话每一个小粒度的字典都需要
存放一次 100,这就是为何无序状态下 10M 粒度的字典 size 远大于 382M 的字典 size.在这
中国科学院计算技术研究所先进计算机系统实验室
10
组测试中,小粒度的总 size 631M 大于大粒度的 452M,说明字典 size 的影响更大,原因之
一是当前字典编码中一个字典值是用 4 个字节即 32bit 来保存的,而字典项 ID 的位编码的
一个数值只能减少少数几个 bit 而已。
这里想做的总结是,parquet 的字典编码只适合于值重复次数很多的情况,在满足这种
情况的前提下,如果是无序的,则最好采用较大的粒度,如果是有序的,则最好采用较小的
粒度。
4.4.2. L_partkey sortL_partkey
图 3 l_partkey sortl_partkey 压缩比
0.85
1.66
0.99
0.06
0.99
0.56
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
Parquet.DeltaBinaryParquet.DictionaryRleBitORC.RLE
压缩比
压缩算法
l_partkey(int)
l_partkey压缩比
sortl_partkey压缩比
整型数据(byte int long)编码性能的综合测试报告
11
图 4 l_partkey sortl_partkey 编码解码时间
4.4.2.1 分析
1) 对 于 未 排 序 的 l_partkey 来 说 , 三 者 都 不 理 想 ,
parquet.deltaBinaryBitpackingZigzar 效果不好主要应为相邻数值的增量差较大
且无规律,parquet.dictionaryRleBitPackingVlq 为副作用,则在与小粒度保存的
重复值太多,且字典 ID 的编码效果有限。ORC.RLE 几乎没做用则在与无序的
情况下 RLE 这种依赖重复值和等差数列的编码方式几乎无效。
2) 对于 sortL_partkey 而言,排序后,parquet.deltaBinaryBitpackingZigzar 性能最好,
是因为相邻数值增量差变小,ORC.RLE 也受排序的影响,使得其依赖重复值
和等差数列的风格得到一定满足,parquet.dictionaryRleBitPackingVlq 几乎没效
果则是由于其未对字典进行编码和针对字典 ID 编码不合适引起的。
3) 编码解码时间来看,一般情况下是 parquet.deltaBinaryBitpackingZigzar 最优,
在于其较好利用了位运算,而字典编码的时间问题前面已经分析过。
3.659
83.058
6.62
2.458
9.567
6.671
2.379
38.875
5.086
1.937
6.253
4.143
0
10
20
30
40
50
60
70
80
90
Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE
编码解码时间(s)
压缩算法
l_partkey(int) l_partkey编码
时间
中国科学院计算技术研究所先进计算机系统实验室
12
4.4.3. l_linenumber sortL_linenumber
图 5 l_linenumber sortl_linenumber 压缩比
图 6 l_linenumber sortll_linenumber
0.11
0.09
0.18
0.0097
0.0000015
0.006
0
0.02
0.04
0.06
0.08
0.1
0.12
0.14
0.16
0.18
0.2
Parquet.DeltaBinaryParquet.DictionaryRleBit ORC.RLE
压缩比
压缩算法
l_linenumber(int)
l_linenumber压缩比
sortl_linenumber压缩比
2.395
5.848
3.512
2.079
3.124
2.594
2.133
4.262
1.438
2.067
2.27
1.274
0
1
2
3
4
5
6
7
Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE
编码解码时间(s)
压缩算法
l_linenumber(int)
l_linenumber编码时间
l_linenumber解码时间
sortl_linenumber编码时间
sortl_linenumber解码时间
整型数据(byte int long)编码性能的综合测试报告
13
4.4.3.1 分析
1) 在这种包含大量重复值的情况下 parquet 的字典编码终于发挥了优势,其在排序
和不排序的情况下都是最优,对未排序的 l_linenumber 的字典 ID 大小是 36M,
这个地方还有较大的可优化之处,核心是好好利用 bit encoding.
字典编码的编码和解码时间还是较另外两者有一定的劣势,不过这种差距
相 比 前 两 组 数 倍 的 差 距 的 减 小 了 许 多 。 ORC.RLE 在 对 排 序 之 后 的
sortL_linenumber 的编码效果终于比 parquet 的增量编码有了一定优势,未排序
情况下,parquet 的增量编码的效果优于 ORC.RLE.
4.4.4. l_returnflag sortL_returnflag
图 7 l_returnflag sortl_returnflag 压缩比
1.53
0.25
0.61
0.08
6E-06 0.015
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE
压缩比
压缩算法
l_returnflag(byte)
l_returnflag压缩比
sortl_returnflag压缩比
中国科学院计算技术研究所先进计算机系统实验室
14
图 8 l_returnflag sortl_returnflag 编码解码时间
4.4.5. l_linestatus sortL_linestatus
图 9 l_linestatus sortl_linestatus 压缩比
143.164
166.269
12.369
143.97
104.28
6.376
133.316
154.664
4.066
142.934
96.028
2.712
0
20
40
60
80
100
120
140
160
180
Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE
编码解码时间(s)
压缩比
l_returnflag(byte)
l_returnflag编码时间
l_returnflag解码时间
sortl_returnflag编码时间
sortl_returnflag解码时间
0.71
0.15
0.28
0.08
6E-06 0.015
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE
压缩比
压缩算法
l_linestatus(byte)
l_linestatus压缩比
sortl_linestatus…
整型数据(byte int long)编码性能的综合测试报告
15
4.4.5.1 分析
1) L_returnflag 和 l_linestatus 的值分布情况和最后的测试结果很类似,所以在这里一
起分析。Parquet 的字典编码和增量编码的编码和解码时间都远远高于 ORC.RLE,主要原因是
在 于 前 两 者 在 对 byte 值 进 行 编 码 的 时 候 需 要 将 byte 包 装 成 字 符 串
cw.writeBytes(Binary.fromString("" +initbytes[i])),而解码的时候则需要将字符串还原成 byte
值,result[i]=Byte.parseByte(cr.readBytes().toStringUsingUTF8()),这是很耗时间的。而 Parquet
的字典编码慢于 Parquet 的增量编码的原因在于字典编码需要对字典和字典项 ID 同时处理。
在未对L_returnfalg 排序的情况下,parquet 的字典编码效果相对最佳,但是其时间太长。
在排序之后,parquet 的字典编码也是最好,但编码和解码时间相对于 ORC.RLE 来说还是过
长,况且 ORC.RLE 的压缩效果也是稍微差于 parquet 的字典编码。
137.542
169.955
9.275
146.734
101.324
4.684
133.311
155.189
4.789
142.949
95.181
3.142
0
20
40
60
80
100
120
140
160
180
Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE
编码解码时间(s)
压缩算法
l_linestatus(byte)
l_linestatus编码时间
l_linestatus解码时间
sortl_linestatus编码时间
sortl_linestatus解码时间
中国科学院计算技术研究所先进计算机系统实验室
16
4.4.6. P_channel_tv sortp_channel_tv
4.4.6.1 分析
1) 对于这种值随机分布的情况而言,可以看出在位排序的情况下,只有字典编码
起到了一定作用,主要还是由于 byte 取值个数是 256 个而使得字典 size 很小所
1.84
0.88
1.01
0.08
0.00001 0.013
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
1.8
2
Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE
压缩比
压缩算法
p_channel_tv(byte)
p_channel_tv压缩比
sortp_channel_tv压缩比
138.823
181.358
6.462
143.122
105.208
4.451
134.107
155.377
4.785
139.064
96.152
2.491
0
20
40
60
80
100
120
140
160
180
200
Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE
编码解码时间(s)
压缩算法
p_channel_tv(byte)
p_channel_tv编码时间
p_channel_tv解码时间
sortp_channel_tv编码时
间
sortp_channel_tv解码时
间
整型数据(byte int long)编码性能的综合测试报告
17
引起,但是 parquet 的两种编码的时间都较 ORC 的 RLE 长很多,一个重要原因
就是把 byte 包装成 String 类型进行处理耗时很长。
2) 排序之后,三种编码的编码压缩比效果都很少,都极大利用了编码本身的特性。
但是可以看出,结合编码解码时间,ORC.RLE 性能最高。
4.5. 结论
衡量一种编码算法性能优劣的主要指标是压缩比,编码时间,解码时间。同时编码编码
的是否通用也是需要考虑的一个点。结合理论分析和实验结果,我们对上述编码做出如下结
论:
4.5.1. Int 类型结论
1) 一般而言,字典编码不管是从压缩比还是编码时间,解码时间来看都比增量编
码和 RLE 编码要差很多,通常不予考虑。即便是对于非重复值很少的特殊数值
分布,字典编码的压缩比纵然很好,但是其编码解码时间还是差很多,而增量
编码和 RLE 编码此时的压缩也是很好只是差字典编码一点点,但是时间上却优
化很多。当然字典编码适合于那种只考虑压缩比而不太关注编码解码时间对的
情形,比如说某列的数据只需要保存起来却又很少进行查询。
2) 接下来对比增量编码和 RLE 编码。由于增量编码不需要要求值分布是成连续重
复或者是等差排列的情况,其适合场景当然要比 RLE 要广泛。即便是适合 RLE
的值分布是成连续重复或者是等差排列的情况,增量编码同样也充分能利用这
个数值的分布特性来进行编码压缩。再者,考虑到增量编码内部采用了更适合
机器运算的位运算,所以其在编码解码时间上而言一般比 RLE 要快。只有在非
重复值出现很少且是排序的情况下,RLE 在压缩比以及编码解码时间才比增量
编码有较小的优势,而这种情况对值分布要求很严格,还要求是有序的。
3) 所以我们在一般情况下选择增量编码最为合适。
4.5.2. Byte 型结论
1) parquet 对于 byte 类型的增量编码不管是在压缩比还是编码解码时间上而言都是
很差,可以首先排除掉。不过需要注意的是,其编码解码时间较慢的一个很重
要 原 因 是 byte 值 进 行 编 码 的 时 候 需 要 将 byte 包 装 成 字 符 串
cw.writeBytes(Binary.fromString("" +initbytes[i])) , 解 码 的 时 候 则 需 要 用
result[i]=Byte.parseByte(cr.readBytes().toStringUsingUTF8()),这是很耗时间的。
2) 而对于 parquet 的字典编码和 Orc 的 RLE 可以发现,RLE 在编码解码时间上占
有绝对的优势。虽然对于值随机分布的情况而言,字典编码较 RLE 编码有一定
的优势(主要是应为 byte 只能取 256 个值,字典 size 很小),但是其编码解码时
间还是太长,当然字典编码编码解码时间也受到和增量编码同样的时间困扰,
就是把 byte 包装成字符串进行处理。而对于有限的 byte 类型而言,RLE 和字典
编码性能都特别好,后者性能要略优于前者。但是其编码解码时间太拖后腿了,
对于只需要一次加载而需要多次查询的一般情况而言,这也是不适合的。
3) 在更好优化字典编码的编码解码时间之前,RLE 编码是一个相对不错的选择。
如何更好的优化字典编码的编码解码时间是一个关键问题。
中国科学院计算技术研究所先进计算机系统实验室
18
5. 编码展望
截止到现在,我们所做的所有测评分析都是已经成型的编码算法,我们也发现了这些编
码存在的一些可以改进的地方,比如说针对 byte 类型编码采用的把 byte 包装成字符串的这
种耗时的处理,对字典本身采用增量位编码的编码方式,把 ORC 的 RLE 编码和位编码更好
的结合起来,让 Parquet 的 RLE 编码支持对等差数列的编码,合理的设置位编码,增量编码
的基本编码粒度。除了对现有的编码方式的内部进行优化之外,也可以考虑组合出更加高效
的编码方式。比如说把google protobuffer 编码结合ORC的RLE,字典编码结合增量编码等。
对于如何依据值分布情况采用最佳编码,核心是统计出值的分布情况,而不需要有用户
认为辨别。在数据加载的时候实现数据统计功也是以后需要考虑的一个方向。在决定采用那
种编码压缩方式的时候,需要权衡压缩比,编码时间,解码时间的比重,如何能得出一个较
为合理的量化公式也是可以考虑的一个方向。
参考文献
1. https://github.com/Parquet/parquet-format/blob/master/Encodings.md#run-length-encoding--b
it-packing-hybrid-rle--3
2. http://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.0.0.2/ds_Hive/orcfile.html
3. http://code.google.com/p/protobuf/
4. http://lemire.me/blog/archives/2012/03/06/how-fast-is-bit-packing/
5. http://lemire.me/blog/archives/2012/04/05/bit-packing-is-fast-but-integer-logarithm-is-slow/
6. http://lemire.me/blog/archives/2012/10/23/when-is-a-bitmap-faster-than-an-integer-list/
7. http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
8. http://lemire.me/blog/archives/2009/11/13/more-database-compression-means-more-speed-rig
ht/
9. http://lemire.me/blog/archives/2012/02/08/effective-compression-using-frame-of-reference-an
d-delta-coding/
10. http://en.wikipedia.org/wiki/Vectorization_(parallel_computing)
11. http://lemire.me/blog/archives/2012/09/12/fast-integer-compression-decoding-billions-of-inte
gers-per-second/

Contenu connexe

Similaire à Deep learning wiki on data encodingi

网管会 一些基础知识
网管会 一些基础知识网管会 一些基础知识
网管会 一些基础知识Jammy Wang
 
中文编码杂谈
中文编码杂谈中文编码杂谈
中文编码杂谈Xiaozhe Wang
 
張逸 - 研究所 / 轉學考計算機概論 、公職計算機概要 - 基本計概 - 試閱版
張逸 - 研究所 / 轉學考計算機概論 、公職計算機概要 - 基本計概 - 試閱版張逸 - 研究所 / 轉學考計算機概論 、公職計算機概要 - 基本計概 - 試閱版
張逸 - 研究所 / 轉學考計算機概論 、公職計算機概要 - 基本計概 - 試閱版逸 張
 
计算机应用基础课件(一)
计算机应用基础课件(一)计算机应用基础课件(一)
计算机应用基础课件(一)51 lecture
 
基于嵌入式系统的Avs P10编码系统设计
基于嵌入式系统的Avs P10编码系统设计基于嵌入式系统的Avs P10编码系统设计
基于嵌入式系统的Avs P10编码系统设计Hengyi
 
基本遗传算法
 基本遗传算法 基本遗传算法
基本遗传算法sixu05202004
 
Tokyo Cabinet
Tokyo CabinetTokyo Cabinet
Tokyo Cabinetrewinx
 
Tokyo Cabinet Key Value数据库及其扩展应用
Tokyo Cabinet  Key Value数据库及其扩展应用Tokyo Cabinet  Key Value数据库及其扩展应用
Tokyo Cabinet Key Value数据库及其扩展应用rewinx
 
我对后端优化的一点想法
我对后端优化的一点想法我对后端优化的一点想法
我对后端优化的一点想法mysqlops
 
電腦常識(含計算機大意) 中油.台水.捷運.中華電學儒
電腦常識(含計算機大意) 中油.台水.捷運.中華電學儒電腦常識(含計算機大意) 中油.台水.捷運.中華電學儒
電腦常識(含計算機大意) 中油.台水.捷運.中華電學儒TAAZE 讀冊生活
 
Pdf unspecified 865330
Pdf unspecified 865330Pdf unspecified 865330
Pdf unspecified 865330Dante Lupu
 
基于Innodb开发的最佳实践
基于Innodb开发的最佳实践基于Innodb开发的最佳实践
基于Innodb开发的最佳实践wubx
 
第1章 Matlab操作基础
第1章  Matlab操作基础第1章  Matlab操作基础
第1章 Matlab操作基础eterou
 
networking performance
networking performancenetworking performance
networking performance朋 王
 
Excel函數進階班(北市政府公訓處) 2
Excel函數進階班(北市政府公訓處) 2Excel函數進階班(北市政府公訓處) 2
Excel函數進階班(北市政府公訓處) 2terry28853669
 
第11章 目标代码生成
第11章 目标代码生成第11章 目标代码生成
第11章 目标代码生成tjpucompiler
 
ICT_old_ch03-converted.pptx
ICT_old_ch03-converted.pptxICT_old_ch03-converted.pptx
ICT_old_ch03-converted.pptxliutommy1
 

Similaire à Deep learning wiki on data encodingi (20)

网管会 一些基础知识
网管会 一些基础知识网管会 一些基础知识
网管会 一些基础知识
 
中文编码杂谈
中文编码杂谈中文编码杂谈
中文编码杂谈
 
張逸 - 研究所 / 轉學考計算機概論 、公職計算機概要 - 基本計概 - 試閱版
張逸 - 研究所 / 轉學考計算機概論 、公職計算機概要 - 基本計概 - 試閱版張逸 - 研究所 / 轉學考計算機概論 、公職計算機概要 - 基本計概 - 試閱版
張逸 - 研究所 / 轉學考計算機概論 、公職計算機概要 - 基本計概 - 試閱版
 
Ch2 1
Ch2 1Ch2 1
Ch2 1
 
计算机应用基础课件(一)
计算机应用基础课件(一)计算机应用基础课件(一)
计算机应用基础课件(一)
 
基于嵌入式系统的Avs P10编码系统设计
基于嵌入式系统的Avs P10编码系统设计基于嵌入式系统的Avs P10编码系统设计
基于嵌入式系统的Avs P10编码系统设计
 
基本遗传算法
 基本遗传算法 基本遗传算法
基本遗传算法
 
Tokyo Cabinet
Tokyo CabinetTokyo Cabinet
Tokyo Cabinet
 
Tokyo Cabinet Key Value数据库及其扩展应用
Tokyo Cabinet  Key Value数据库及其扩展应用Tokyo Cabinet  Key Value数据库及其扩展应用
Tokyo Cabinet Key Value数据库及其扩展应用
 
我对后端优化的一点想法
我对后端优化的一点想法我对后端优化的一点想法
我对后端优化的一点想法
 
電腦常識(含計算機大意) 中油.台水.捷運.中華電學儒
電腦常識(含計算機大意) 中油.台水.捷運.中華電學儒電腦常識(含計算機大意) 中油.台水.捷運.中華電學儒
電腦常識(含計算機大意) 中油.台水.捷運.中華電學儒
 
Pdf unspecified 865330
Pdf unspecified 865330Pdf unspecified 865330
Pdf unspecified 865330
 
基于Innodb开发的最佳实践
基于Innodb开发的最佳实践基于Innodb开发的最佳实践
基于Innodb开发的最佳实践
 
第1章 Matlab操作基础
第1章  Matlab操作基础第1章  Matlab操作基础
第1章 Matlab操作基础
 
networking performance
networking performancenetworking performance
networking performance
 
第1章
第1章第1章
第1章
 
Ch1 教學
Ch1 教學Ch1 教學
Ch1 教學
 
Excel函數進階班(北市政府公訓處) 2
Excel函數進階班(北市政府公訓處) 2Excel函數進階班(北市政府公訓處) 2
Excel函數進階班(北市政府公訓處) 2
 
第11章 目标代码生成
第11章 目标代码生成第11章 目标代码生成
第11章 目标代码生成
 
ICT_old_ch03-converted.pptx
ICT_old_ch03-converted.pptxICT_old_ch03-converted.pptx
ICT_old_ch03-converted.pptx
 

Deep learning wiki on data encodingi

  • 1. 整型数据(byte int long)编码性能的综合测试报告 技术报告 中国科学院计算技术研究所先进计算机系统实验室系统结构组 王猛 2014.03.20 摘 要 本文主要是整型数据的所采用的各种基本编码及其组合编码方式进行了理论分析,指出 每种编码适合的分布类型和优缺点,并采用多组实验进行分析说明,指出了对这些编码进行 改进和重组的一些想法,以及关于编码的一点展望。 1. 调研编码的动机 对于保存在 hdfs 文件系统上的数据而言,优秀的编码方式主要有以下有点:减小磁盘 存储空间,减少 sql 查询从磁盘读取的数据量即磁盘 IO,从而提高查询效率。一个优秀的编 码方式主要是结合数据类编码数据的类型及其 value 的分布情况,如:随机分布,重复值很 多且不连续的分布,重复值较多且连续的分布,等差数列分布,相邻数值增量差很小的分布, 值随机分布但总的个数较少的分布。每一种分布情况都有一种最适合它的编码算法。而如何 统计出值的分布情况则是一个关键点。一般而言,评价一个编码性能好坏最直观的标准是: 压缩比,编码时间,解码时间。结合 Hive 的实际情况,一般而言,对于数据,我们进行的 更多的操作是查询,所以说解码的时间要求更为高一些。通常可以这么认为,在压缩比差别 不是很大的情况下,尽量选择解码时间短的编码方式。当然这只是一般情况。还有很多结合 具体应用的情况,比如说,有些列的数据就很少会被查询到,这样子的话,压缩比当然是首 要因素了。 2. 基本编码方式的分析 2.1. Parquet 部分的整型编码: Parquet 的整数编码主要分为 plain Encoding ,Dictionary Encoding,Delta Encoding, bit-packing Enconding 和 Run Length Encoding 基本编码。 2.1.1. Plain Encoding 最简单编码。即按照 value 出现的顺序依次进行存储,唯一需要注意的是,在存储值的 时候采用的是 little endian,对于像 Int 这样由多个字节组成的数值类型,其采用的是先存储 低位字节,然后存储高位字节。原因是发现通过对 Integer.reverseBytes(in.readInt())和 keep a member byte[4], wrapped by an IntBuffer with appropriate endianness set and call IntBuffer.get() 这两个方法的测试,小端存储比大端存储更快。 2.1.1.1 优缺点以及适合场景 优点:最普通的编码,基本无。
  • 2. 中国科学院计算技术研究所先进计算机系统实验室 2 缺点:实际上没有起到任何节省空间的效果。 适合场景:在其他编码均不能起作用的情况下 2.1.2. Dictionary Encoding 字典编码主要由字典中的字典值以及存储 value 的字典项编号组成。比如:现在字典是 5(1),8(2),10(3) 其字典值是 5,8,10.对应的字典编号是 1,2,3.现在需要存储数值 5,8,5,10,8. 那么存储的顺序值就是其 id 号,即 12132. 2.1.2.1 优缺点以及适合场景 优点:对于非重复值很少的情况特别适合,其中 byte 型由于最多去 256 个 value,可以 认为随机分布的 byte 在压缩比这一块最适合的是字典编码。 缺点:字典编码的 size 由字典 size 和字典项 ID 的 size 两部分,对每一个 value 进行编 码和解码都需要和字典和字典项 ID 打交道,这是其在实际场景中编码解码都很耗时的原因 之一。字典编码的效果主要受限于非重复值的个数及其分布情况,以及字典编码的粒度,实 验中发现字典编码在某些情况下会出现比原始数据还大的最差情况。 适合场景:byte 型,非重复值很少 2.1.3. Bit-packing Encoding 举例来说明,现在需要存储 java int 类型的 0,1,2,3,4,5,6,7 这 8 个值,在不做任何处理 的情况下需要占用的大小是 4*8 即 32 个字节,32*8 个位。现在采用位编码来存储这些数据: 存储规则是计算需要存储的值中的在最大值的实际占用的有效位。比如上述值中的最大值是 7,其具体存储是 00000000 00000000 00000000 00000111 则其有效位是 111,我们只需要用三个 bit 就可以存储所有比此最大值小的值,所以采用如 下的位编码进行存储,占用的存储空间是 3*8=24 bit,大大节省了存储空间: 十进制数: 0 1 2 3 4 5 6 7 bit 值: 000 001 010 011 100 101 110 111 bit 标签: ABC DEF GHI JKL MNO PQR STU VWX 编码之后如下所示: bit 值: 00000101 00111001 01110111 bit 标签: ABCDEFGH IJKLMNOP QRSTUVWX 2.1.3.1 优缺点以及适合场景 优点:采用有效 2 进制的位数来编码,节省了存储空间。此编码的性能不仅取决于值的 分布情况,还取决于 缺点:节省空间的效果受限于编码基本单元中最大值的有效 2 进制位数,如果值都是很 大的情况下,编码效果不明显。 适合场景:值的有效 2 进制位数较少的情况。 2.1.4. Run Length Encoding 此编码对于连续多次出现的重复编码很有效,这里的 RLE 编码和郭师兄的 RLE 的主要
  • 3. 整型数据(byte int long)编码性能的综合测试报告 3 区别是,其内部使用了前面提到的位编码来存储值和值出现的次序。比如 111222(假设每 个值用一个字节表示,则一共 6 个字节),即 1 3 2 3 。则存储是: 00000001 00000011 00000010 00000011 需要 4 个字节。如果采用位编码的话,则存储是:01 11 10 11 一共 8 个位即可以表达。 2.1.4.1 优缺点以及适合场景 优点:结合了位编码的 RLE 适合于连续出现的重复值较多的情况的编码。 缺点:parquet 的 RLE 编码只能针对重复出现的 value 进行编码,不能对等差数列进行 编码。 适合场景:连续出现重复值 2.1.5. Delta bit -packing Encoding 即增量编码和位编码混合编码。以 7,5,3,1,2,3,4,5 为例:先计算出两个相邻的值的增量, 分别为 -2 -2 -2 1 1 1 1 ,在计算的同时保存最小的增量值,这里是-2.需要注意的是最小的 增量值-2 使用 zigzag VLQ int(此时-2 变为 3)类型来保存的。接下来对-2 -2 -2 1 1 1 1 分别 减去最小的增量值-2,则变为 0,0,0,3,3,3,3 ,最大值 3 的二进制代码为 0000000 0000000 0000000 000000011 有效编码是 11 两位,那么就使用 2 个 bit 来保存所有的增量差, 所以这 里用一个 byte 来保存 width 2.对这个序列采用位编码。即依次为 00 00 00 11 11 11 11 。增量 编码保存值的顺序为:first value(7 zigzag VLQ int 变为 14) minimum delta(- 2 zigzag VLQ int 变为 3) bitwidth(2 1byte) bitcode(00 00 00 11 11 11 11) .所以 7,5,3,1,2,3,4,5 的增 量编码为:00001110(14) 00000011(3) 00000010(2) 00000011 111111 共计花费 8+8+8+14=38 位,比原先的 32*8=256 位减少很多。 在这里简要说一下 ZigZag VLQ int,这种编码风格源自于 google protobuffer, zigzag 主要 是应对针对负数的编码,该编码会将有符号整型映射为无符号整型,以便绝对值较小的负数 仍然可以有较小的 varint 编码值,如-1.下面是 ZigZag 对照表: Signed Original Encoded As 0 0 -1 1 1 2 -2 3 2147483647 4294967294 -2147483648 4294967295 其公式为: (n << 1) ^ (n >> 31) //sint32 (n << 1> ^ (n >> 63) //sint64 需要补充说明的是,Protocol Buffer 在实现上述位移操作时均采用的算术位移, 因此对于(n >> 31)和(n >> 63)而言,如果 n 为负值位移后的结果就是-1,否则就是 0。 2.1.5.1 优缺点以及适合场景 优点:此种编码是在值随机分布情况中综合性能最好的,它不要求你的值是连续重复或 者是等差数列,也不受限于数据的有效 2 进制位的个数,仅仅希望相邻数值的增量差小点就
  • 4. 中国科学院计算技术研究所先进计算机系统实验室 4 行。此编码的性能除了收到相邻数据的增量的差的大小的影响,还受到一个人为设定的基本 粒度的大小的影响,应为其采用的位编码的 2 进制位的个数取决于基本编码粒度中最大的增 量差的有效 2 进制位数。 缺点:如果相邻数值的增量差波动很大,那么编码效果有限 适合场景:相邻 value 增量差较小 2.2. ORC 的整型编码调研 2.2.1. 位编码 位编码适合于用来存储 NULL 值,如果值为 NULL,则用 bit 0 表示,否则用 bit 1 表示 不为 NULL(此时需结合其他编码)。 2.2.2. RLE 编码 对于 int,long,short 类型的字段,使用 RLE 编码。该编码能够对等差数列(完全相等也 属于等差数列)进行压缩,该等差数列需要满足以下两个条件: 1.至少有含3个元素满足等差数列 2.差值在-128~127之间(因为差值用1Byte 来表示) Run-Length 的具体存储如下: 第一个 Byte 是 Control Byte,取值在-128~127之间,其中-1~-128代表后面存储着 1~128个不满足等差数列的数字,0~127代表后面存储着3~130个满足等差数列的数字; 如果 Control Byte>=0,则后面跟着一个 Byte 存储等差数列的差值,否则跟着-Control Byte 这个负数。 如果 Control Byte>=0,则继差值之后跟着等差数列的第一个数。 例子: 原始数字:12,12,12,12,12,10,7,13 经过 Run-Length 的数字:2, 0,12,-3,10,7,13 绿色代表 Control Byte,蓝色代表差值,黑色代表具体的数字。 细节提示,在 RLE 编码中,可以用一个 byte 来存储控制位,一个 byte 来存储数列的差 值,这样可以节省存储空间,毕竟实际情况几乎没有长度到达2的31次方的等差数列,也没 有差值达到2的31次方的等差数列。 2.1.4.1 优缺点以及适合场景 优点:除了可以对连续出现的重复值进行编码外,也可以对等差数列进行编码
  • 5. 整型数据(byte int long)编码性能的综合测试报告 5 缺点:和 parquet 相比,没有利用位编码进一步节省空间 适合场景:连续出现重复值或者等差数列较多 2.2.3. Variable-width Encoding 基于 Google's protocol buffers ,是使用一个或多个字节表示整型数据的方法(字节是此 编码的基本单元)。其中数值本身越小,其所占用的字节数越少. 在 varint 中,每个字节中 都包含一个 msb(most significant bit)设置(使用最高位),这意味着其后的字节是否和当前字 节一起来表示同一个整型数值。而字节中的其余七位将用于存储数据本身。如果高位是 1 则表示后面还有字节来表示同一个整数值,如果高位是 0 则表示此字节是此数的最后一个字 节。通常而言,整数数值都是由字节表示,其中每个字节为 8 位,即 Base 256。然而在 Protocol Buffer 的编码中,最高位成为了 msb,只有后面的 7 位存储实际的数据,因此我们称其为 Base 128(2 的 7 次方)。考虑到此高位的值的含义已经取代了符号位的含义,那么对于负数 的编码,需要先使用 zigzag 编码把负数映射为非负数。这种编码对于小的值的存储比较有 效果。 由于 Protocol Buffer 是按照 Little Endian 的方式进行数据布局的,因此我们这里需要将 两个字节的位置进行翻转 比如数字 1,它本身只占用一个字节即可表示,所以它的 msb 为其本身的值,如: 0000 0001 再比如十进制数字 300,它的编码后表示形式为: 1010 1100 0000 0010 对于Protocol Buffer 而言又是如何将上面的字节布局还原成300呢?这里我们需要做的 第一步是 drop 掉每个字节的 msb。从上例中可以看出第一个字节(1010 1100)的 msb(最 高位)被设置为 1,这说明后面的字节将连同该字节表示同一个数值,而第二个字节(0000 0010)的 msb 为 0,因此该字节将为表示该数值的最后一个字节了,后面如果还有其他的字 节数据,将表示其他的数据。 1010 1100 0000 0010 -> 010 1100 000 0010 上例中的第二行已经将第一行中每一个字节的 msb 去除。由于 Protocol Buffer 是按照 Little Endian 的方式进行数据布局的,因此我们这里需要将两个字节的位置进行翻转。 010 1100 000 0010 -> 000 0010 010 1100 //翻转第一行的两个字节 -> 100101100 //将翻转后的两个字节直接连接并去除高位 0 -> 256 + 32 + 8 + 4 = 300 //将上一行的二进制数据换算成十进制,其值为 300. 上面的举例是反编码,下面举例如何编码为 Protocol Buffer. 先表示具体值----从低位开始以 7 为模划分,不足的补为 0----翻转数据(小端存储) -----添加 msb 值 0 OR 1. 比如 java int 137 ,其不做编码的二进制表示为 0000000 00000000 00000000 10001001 需要 4 个字节,有效位是 10001001,对其进行处理:
  • 6. 中国科学院计算技术研究所先进计算机系统实验室 6 1. 7 bit 一组,把二进制分开,不足的补 0 ,变成 0000001 0001001 翻转数据,0001001 0000001 2. 把最低的 7 位拿出来,在最高位补 0 表示最后一位,变成 00000001,这个作为最低 位,放在最后边。 3. 在其他组的最高位补 1 ,表示没有结束,后面跟着还有数据。在这里就是 10001001 4. 拼在一起,就变成了 10001001 00000001 只需要两个字节就可以存储。 3. 组合编码 第 2 部分里面我们对一些基本编码进行了较为详细的分析,每一种基本编码的适合场景 条件限制很多,所以需要结合相关特点进行组合。实际情况下把上述各种编码组合起来的效 果更加,我们主要分为 3 类符复合编码。 编 码来源 编 码方式 优点 缺点 典 型应用 是否发现 改进点 Parquet Delta bit packing Encoding 充分结合了增量编码和 位编码的优势,增量编码对于那 种不重复出现的随机分布的数 值进行编码最合适不过了。鉴于 是对 int 序列的相对增量进行 编码,所以一般就不会受 int 值 本身大小的影响,一般不会存在 前面位编码受较大值的影响的 情况。此处需要规避负数的位编 码问题,如果序列的增量出现了 负数,则需要以序列的增量中的 最小负数为基准,为每一个增量 值加上此最小负数的绝对值 对于连续多次出现重复值的情况,可能 性 能 不 及 RLE 编 码 。 对 于 11111111112222222222 这样的序列:RLE 编 码为:1 10 2 10 代价为 4 个字节(如果 RLE 内部还使用 bit-packing 的话就更小了)。 Delta bit packing Encoding 编码则会 偏大,究其原因是此编码不能很好利用重复值 情况,即使 delta 是 0,那么得用一个 zigzag VLQ INT 来保存 0,一个 byte 来保存 0,然后每两个 相邻值的差值还得用一个 bit 0 存储。 特 别 适合于值分 布随机无明 显规律的情 况,但是最 好是相邻两 个值的增量 不要过大, 不然会影响 位编码的性 能 合理的确定 一个长度的数组作 为基本单元,此基 本单元的所有数值 的 bit 长度取决于 此数组对负增量修 正 后 的 最大 增 量 值 , 所 以要 确 保 delta 不要过大。还 有就是是否可以让 此编码增加对连续 重复值的支持。 组 合 Parquet Dicti onary Encoding +bit-packing Enconding+ Run Length 总体上采用字典编码,内 部依据字典项 id 连续出现的情 况采用 RLE-Bit Packing (连续 出 现 重 复 次 数 多 ) 或 者 bit packing 编码(值分布随机) 考虑到此处的位编码是 用于对字典项 Id 进行编码,id 当然是非负数,规避了负数的位 编码问题) 关于界定何时使用单纯的位编码还是使 用 RLE 和位编码的混合编码。以及是否可以考 虑在字典内部也采用位编码保存,而不仅仅是 对字典项 id 使用位编码 适 合 于重复值较 多 的 情 况 (不论是否 连续出现), 不适合值分 布随机的情 况 字典内部是否可以 支持位编码,或者 说是字典内部对值 的保存采用 Google's protocolbuffers 的 variable-width ORC RLE 相比于 parquet 中的只能 对重复值进行编码的 RLE 的情 况,增加了对等差数列的编码支 持。适合于等差序列的值的编 码,即使出现的值是随机分布 的,也仅需要一个 byte 大小的 控制位的额外存储。 未能考虑对存储的value的有效位进行编 码。 重 复 值较多或等 差数列较多 内部可以嵌 入位编码 4. 测试报告 4.1. 测试说明 此次测试涉及到的编码是可靠且正确的,对于编码和解码的时间,也是通过对源码细节 的理解,卡的比较精确。对于 int 类型而言,总大小为 382M,以 10M 为粒度进行测试,总 共执行 39 次的编码和解码操作。对于 byte 类型而言,总大小为 382M,以 2.5M 为粒度进行 测试,总共执行 153 次的编码和解码操作。
  • 7. 整型数据(byte int long)编码性能的综合测试报告 7 测试遵循单一变量原则,可以认为此次测试有一定的代表性。 4.2. 测试环境 内存 磁盘空间 cpu OS Linux 内核 4G 900G 1 cpu X 4 cores Centos 6.2 2.6.32 4.3. 测试数据类型和分布情况 来源 类型 大小 有序 值分布情况 tpch-lineite m:l_orderkey int 382M 是 有序且有较少数目的重复值,相邻数值增量 差较小 1161273537 1161273538 1161273538 1161273538 1161273538 1161273539 1161273539 1161273539 1161273539 1161273540 1161273540 tpch-lineite m:l_partkey int 382M 否 随机分布,相邻数据的增量较大且无规律 如 : 12121910 3173943 24450539 20206290 7113357 34190843 5490008 30561624 9208575 8517641 35984160 25763416 5729027 21656575 22047084 9951961 22600207 7801511 tpch-lineite m:l_partkey(sort) int 382M 是 排序之后重复值出现在一起,相邻数据的 差值较小 tpch-lineite m:l_linenumber int 382M 否 相邻数值增量很小,且存在等差数列,取 值个数也很少 3 4 5 6 7 1 2 3 4 5 6 1 2 3 1 2 3 4 5 6 1 2 3 4 5 6 7 1 1 1 2 3 4 5 1 2 1 2 3 4 tpch-lineite m:l_linenumber(so rt) int 382M 是 排序之后出现很长很长的重复值串 tpch-lineite m:l_returnfalg byte 382M 否 取值局限于 78,82,65 三个值,且存在一定 的连续重复情况,如:78 82 82 65 65 65 82 82 78 78 78 78 78 82 65 65 82 78 65 78 78 78 78 78 tpch-lineite m:l_returnfalg(sort ) byte 382M 是 排序之后出现很长很长的重复值串 tpch-lineite m:l_linestatus byte 382M 否 虽然无序,但取值局限于 2 个值:79,70,且 出现较长的连续重复串 如:79 79 79 79 79 79 70 70 70 79 79 797979 79 79 79 79 70 70 70 70 tpch-lineite m:l_linestatus(sort) byte 382M 是 排序之后出现很长很长的重复值串 tpc-ds- promotion : p_channel-tv byte 382M 否 随机分布,无明显规律 tpc-ds- promotion : p_channel-tv(sort) byte 382M 是 排序之后,呈现大片的连续重复的 value 4.4. 测试结果说明 4.4.1. L_orderkey(默认有序)
  • 8. 中国科学院计算技术研究所先进计算机系统实验室 8 图 1 l_orderkey 压缩比 图 2 l_orderkey 编码解码时间 4.4.1.1 分析 1)Parquet 的 deltabianryPackinZigzar 编码优势明显,主要在于默认有序的 l_orderkey 相邻数值的增量差比较小; 2)Orc 的 RLE 也有 0.47 的压缩率,一是在于默认有序的了——orderkey 有一定的连续 出 现 的 重 复 值 和 等 差 数 列 , 至 于 此 RLE 的 编 码 和 解 码 时 间 较 Parquet 的 0.18 0.88 0.47 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1 Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE 压缩比 压缩方式 l_orderkey(int) 2.57 23.838 4.537 1.978 5.199 3.339 0 5 10 15 20 25 30 Parquet.DeltaBinaryParquet.DictionaryRleBit ORC.RLE 编码解码时间(s) 压缩方式 l_orderkey(int) 编码时间 解码时间
  • 9. 整型数据(byte int long)编码性能的综合测试报告 9 deltabianryPackinZigzar 长,主要则在于后者运用到了一些更适合机器的位运算; 3)在此组测试中,发现 parquet 的字典编码 dictionaryRleBitPackingVlq 性能很差,就编 码时间的而言其比另外两种编码慢很多,一是因为在字典编码中保存字典项 ID 的编码中, 采用了一个重复值 count 计数器,当连续出现的重复值达到 8 以上的时候采用 RLE 编码, 否则采用位编码。这么做的目的当然是为了获得更好的压缩比,但是针对 id 的判断会大大 增加编码的时间;而编码慢的另外一个原因是编码的时候需要先从字典中获取此 value 的 id, 然后再把此 id 进行 RLE 和 bitpacking 混合编码,相当于对一个 value 编码需要量进行 2 步。 这也是其慢的一个重要原因。而字典编码的解码时间慢则主要在于每次获取一个值的时候除 了需要先对字典项 id 进行解码获得 id 值,然后再依据此 id 从字典中查询相对应的值,也是 需要 2 步才能获得原始 value. 而对于字典编码的编码效果不理想,则分为两点:字典和字典项的问题。在保存字典的 时候,没有采用任何编码对字典进行压缩,在这里个人介意用 deltabitpacking 编码会较大的 减小字典的 size。而就字典 ID 编码而言,其采用的位编码的 size 取决于字典的 size 的有效 二进制位,这样不如 deltabitpacking 起到的压缩效果好。但是,前面已经说过,对字典不做 任何编码的情况下,编码时间本来就很长,此时再添加新的增量编码岂不是会变的更慢?! 如果在字典编码中添加了 deltabitpacking 编码,那么这种字典编码和我们那个只有 deltabianrypackingZigzar 的编码的优势在哪里?是在于对重复值的保存上免去了对重复值的 保存,但是不要忘了我们在用字典编码保存一个值的时候,其实际代价来自于字典和字典项 ID 两个存储代价。 4)需要说明的是,上一次我提交的测试报告中是对 1 亿行数据进行一次整体编码的, 而这一次则是对 int 以 10M 为单位编码,测试结果发现。编码粒度的大小对 parquet 的 deltabinaryPackingZigzar 编码和 ORC 的 RLE 编码几乎没有影响,这也是可以解释的,因为 对于 deltabinaryPackingZigzar 编码而言,我们在编码过程中会选 128byte 大小左右的 size 为 基本增量编码的粒度,这个粒度的选择才是增量的关键,而与外面这个 10M 或者是 382M 的大的粒度没有关系;就 ORC 的 RLE 而言,其编码效果受限与连续数值的分布情况,也和 外面这个 10M 或者是 382M 的大的粒度没有关系; 偏偏就 parquet 的 DictinoaryRleBitPackingVlq 编码受粒度影响很严重。2 组测试显示, 对于 l_orderkey 而言,382M 的粒度的字典总 size 是 99M,字典 ID 是 299M,而 10M 粒度 的字典总 size 也是 99M,字典 ID 是 238M,多了 61M。解释原因如下:由于 l_orderkey 默 认有序,所以重复的字典值是连续重现的,这样的话无论粒度怎么划分,连续出现的某个值 一般是落在同一个粒度块的,这就使得总的字典 size 基本没什么变化,但是为何字典 ID 编 码差距这么大呢?主要在于对于字典项 ID 编码所采用的位编码所致,我们知道采用位编码 的话需要选取一个用来进行位编码的长度。在这里,此长度是由字典的 size 来决定,位宽 bitwidth=字典 size 的有效二进制位的长度。很显然,把 382M 的数据都放在一个字典里的字 典 size 肯定远远大于存放 10M 的数据的字典的 size,所以 10M 这种小粒度的 bitwidth 远远 小于 382M 的位宽,这就导致小粒度 10M 的字典 ID 的编码效果远远好于 382M 的大粒度。 这是对于有序数据而言小粒度和大粒度的差别,下面谈谈无需的时候,小粒度和大粒度的差 别: 和前面分析一样,deltabinaryPackingZigzar 和 ORC.RLE 在无序情况下不受粒度大小的 影响。通过对无序的 l_partkey 的测试显示,382M 粒度的字典大小为 141M,字典项 ID 的 大小为 311M,而 10M 粒度的字典总大小为 370M,字典 ID 为 261M,对于小粒度的字典项 ID 小于大粒度的字典项 ID 的原因上面已经说了,这里解释字典 size.对于无序的数据而言, 有可能有 10 个值为 100 的数据分布在 10 个粒度里面,这样的话每一个小粒度的字典都需要 存放一次 100,这就是为何无序状态下 10M 粒度的字典 size 远大于 382M 的字典 size.在这
  • 10. 中国科学院计算技术研究所先进计算机系统实验室 10 组测试中,小粒度的总 size 631M 大于大粒度的 452M,说明字典 size 的影响更大,原因之 一是当前字典编码中一个字典值是用 4 个字节即 32bit 来保存的,而字典项 ID 的位编码的 一个数值只能减少少数几个 bit 而已。 这里想做的总结是,parquet 的字典编码只适合于值重复次数很多的情况,在满足这种 情况的前提下,如果是无序的,则最好采用较大的粒度,如果是有序的,则最好采用较小的 粒度。 4.4.2. L_partkey sortL_partkey 图 3 l_partkey sortl_partkey 压缩比 0.85 1.66 0.99 0.06 0.99 0.56 0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 Parquet.DeltaBinaryParquet.DictionaryRleBitORC.RLE 压缩比 压缩算法 l_partkey(int) l_partkey压缩比 sortl_partkey压缩比
  • 11. 整型数据(byte int long)编码性能的综合测试报告 11 图 4 l_partkey sortl_partkey 编码解码时间 4.4.2.1 分析 1) 对 于 未 排 序 的 l_partkey 来 说 , 三 者 都 不 理 想 , parquet.deltaBinaryBitpackingZigzar 效果不好主要应为相邻数值的增量差较大 且无规律,parquet.dictionaryRleBitPackingVlq 为副作用,则在与小粒度保存的 重复值太多,且字典 ID 的编码效果有限。ORC.RLE 几乎没做用则在与无序的 情况下 RLE 这种依赖重复值和等差数列的编码方式几乎无效。 2) 对于 sortL_partkey 而言,排序后,parquet.deltaBinaryBitpackingZigzar 性能最好, 是因为相邻数值增量差变小,ORC.RLE 也受排序的影响,使得其依赖重复值 和等差数列的风格得到一定满足,parquet.dictionaryRleBitPackingVlq 几乎没效 果则是由于其未对字典进行编码和针对字典 ID 编码不合适引起的。 3) 编码解码时间来看,一般情况下是 parquet.deltaBinaryBitpackingZigzar 最优, 在于其较好利用了位运算,而字典编码的时间问题前面已经分析过。 3.659 83.058 6.62 2.458 9.567 6.671 2.379 38.875 5.086 1.937 6.253 4.143 0 10 20 30 40 50 60 70 80 90 Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE 编码解码时间(s) 压缩算法 l_partkey(int) l_partkey编码 时间
  • 12. 中国科学院计算技术研究所先进计算机系统实验室 12 4.4.3. l_linenumber sortL_linenumber 图 5 l_linenumber sortl_linenumber 压缩比 图 6 l_linenumber sortll_linenumber 0.11 0.09 0.18 0.0097 0.0000015 0.006 0 0.02 0.04 0.06 0.08 0.1 0.12 0.14 0.16 0.18 0.2 Parquet.DeltaBinaryParquet.DictionaryRleBit ORC.RLE 压缩比 压缩算法 l_linenumber(int) l_linenumber压缩比 sortl_linenumber压缩比 2.395 5.848 3.512 2.079 3.124 2.594 2.133 4.262 1.438 2.067 2.27 1.274 0 1 2 3 4 5 6 7 Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE 编码解码时间(s) 压缩算法 l_linenumber(int) l_linenumber编码时间 l_linenumber解码时间 sortl_linenumber编码时间 sortl_linenumber解码时间
  • 13. 整型数据(byte int long)编码性能的综合测试报告 13 4.4.3.1 分析 1) 在这种包含大量重复值的情况下 parquet 的字典编码终于发挥了优势,其在排序 和不排序的情况下都是最优,对未排序的 l_linenumber 的字典 ID 大小是 36M, 这个地方还有较大的可优化之处,核心是好好利用 bit encoding. 字典编码的编码和解码时间还是较另外两者有一定的劣势,不过这种差距 相 比 前 两 组 数 倍 的 差 距 的 减 小 了 许 多 。 ORC.RLE 在 对 排 序 之 后 的 sortL_linenumber 的编码效果终于比 parquet 的增量编码有了一定优势,未排序 情况下,parquet 的增量编码的效果优于 ORC.RLE. 4.4.4. l_returnflag sortL_returnflag 图 7 l_returnflag sortl_returnflag 压缩比 1.53 0.25 0.61 0.08 6E-06 0.015 0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE 压缩比 压缩算法 l_returnflag(byte) l_returnflag压缩比 sortl_returnflag压缩比
  • 14. 中国科学院计算技术研究所先进计算机系统实验室 14 图 8 l_returnflag sortl_returnflag 编码解码时间 4.4.5. l_linestatus sortL_linestatus 图 9 l_linestatus sortl_linestatus 压缩比 143.164 166.269 12.369 143.97 104.28 6.376 133.316 154.664 4.066 142.934 96.028 2.712 0 20 40 60 80 100 120 140 160 180 Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE 编码解码时间(s) 压缩比 l_returnflag(byte) l_returnflag编码时间 l_returnflag解码时间 sortl_returnflag编码时间 sortl_returnflag解码时间 0.71 0.15 0.28 0.08 6E-06 0.015 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE 压缩比 压缩算法 l_linestatus(byte) l_linestatus压缩比 sortl_linestatus…
  • 15. 整型数据(byte int long)编码性能的综合测试报告 15 4.4.5.1 分析 1) L_returnflag 和 l_linestatus 的值分布情况和最后的测试结果很类似,所以在这里一 起分析。Parquet 的字典编码和增量编码的编码和解码时间都远远高于 ORC.RLE,主要原因是 在 于 前 两 者 在 对 byte 值 进 行 编 码 的 时 候 需 要 将 byte 包 装 成 字 符 串 cw.writeBytes(Binary.fromString("" +initbytes[i])),而解码的时候则需要将字符串还原成 byte 值,result[i]=Byte.parseByte(cr.readBytes().toStringUsingUTF8()),这是很耗时间的。而 Parquet 的字典编码慢于 Parquet 的增量编码的原因在于字典编码需要对字典和字典项 ID 同时处理。 在未对L_returnfalg 排序的情况下,parquet 的字典编码效果相对最佳,但是其时间太长。 在排序之后,parquet 的字典编码也是最好,但编码和解码时间相对于 ORC.RLE 来说还是过 长,况且 ORC.RLE 的压缩效果也是稍微差于 parquet 的字典编码。 137.542 169.955 9.275 146.734 101.324 4.684 133.311 155.189 4.789 142.949 95.181 3.142 0 20 40 60 80 100 120 140 160 180 Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE 编码解码时间(s) 压缩算法 l_linestatus(byte) l_linestatus编码时间 l_linestatus解码时间 sortl_linestatus编码时间 sortl_linestatus解码时间
  • 16. 中国科学院计算技术研究所先进计算机系统实验室 16 4.4.6. P_channel_tv sortp_channel_tv 4.4.6.1 分析 1) 对于这种值随机分布的情况而言,可以看出在位排序的情况下,只有字典编码 起到了一定作用,主要还是由于 byte 取值个数是 256 个而使得字典 size 很小所 1.84 0.88 1.01 0.08 0.00001 0.013 0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2 Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE 压缩比 压缩算法 p_channel_tv(byte) p_channel_tv压缩比 sortp_channel_tv压缩比 138.823 181.358 6.462 143.122 105.208 4.451 134.107 155.377 4.785 139.064 96.152 2.491 0 20 40 60 80 100 120 140 160 180 200 Parquet.DeltaBinary Parquet.DictionaryRleBit ORC.RLE 编码解码时间(s) 压缩算法 p_channel_tv(byte) p_channel_tv编码时间 p_channel_tv解码时间 sortp_channel_tv编码时 间 sortp_channel_tv解码时 间
  • 17. 整型数据(byte int long)编码性能的综合测试报告 17 引起,但是 parquet 的两种编码的时间都较 ORC 的 RLE 长很多,一个重要原因 就是把 byte 包装成 String 类型进行处理耗时很长。 2) 排序之后,三种编码的编码压缩比效果都很少,都极大利用了编码本身的特性。 但是可以看出,结合编码解码时间,ORC.RLE 性能最高。 4.5. 结论 衡量一种编码算法性能优劣的主要指标是压缩比,编码时间,解码时间。同时编码编码 的是否通用也是需要考虑的一个点。结合理论分析和实验结果,我们对上述编码做出如下结 论: 4.5.1. Int 类型结论 1) 一般而言,字典编码不管是从压缩比还是编码时间,解码时间来看都比增量编 码和 RLE 编码要差很多,通常不予考虑。即便是对于非重复值很少的特殊数值 分布,字典编码的压缩比纵然很好,但是其编码解码时间还是差很多,而增量 编码和 RLE 编码此时的压缩也是很好只是差字典编码一点点,但是时间上却优 化很多。当然字典编码适合于那种只考虑压缩比而不太关注编码解码时间对的 情形,比如说某列的数据只需要保存起来却又很少进行查询。 2) 接下来对比增量编码和 RLE 编码。由于增量编码不需要要求值分布是成连续重 复或者是等差排列的情况,其适合场景当然要比 RLE 要广泛。即便是适合 RLE 的值分布是成连续重复或者是等差排列的情况,增量编码同样也充分能利用这 个数值的分布特性来进行编码压缩。再者,考虑到增量编码内部采用了更适合 机器运算的位运算,所以其在编码解码时间上而言一般比 RLE 要快。只有在非 重复值出现很少且是排序的情况下,RLE 在压缩比以及编码解码时间才比增量 编码有较小的优势,而这种情况对值分布要求很严格,还要求是有序的。 3) 所以我们在一般情况下选择增量编码最为合适。 4.5.2. Byte 型结论 1) parquet 对于 byte 类型的增量编码不管是在压缩比还是编码解码时间上而言都是 很差,可以首先排除掉。不过需要注意的是,其编码解码时间较慢的一个很重 要 原 因 是 byte 值 进 行 编 码 的 时 候 需 要 将 byte 包 装 成 字 符 串 cw.writeBytes(Binary.fromString("" +initbytes[i])) , 解 码 的 时 候 则 需 要 用 result[i]=Byte.parseByte(cr.readBytes().toStringUsingUTF8()),这是很耗时间的。 2) 而对于 parquet 的字典编码和 Orc 的 RLE 可以发现,RLE 在编码解码时间上占 有绝对的优势。虽然对于值随机分布的情况而言,字典编码较 RLE 编码有一定 的优势(主要是应为 byte 只能取 256 个值,字典 size 很小),但是其编码解码时 间还是太长,当然字典编码编码解码时间也受到和增量编码同样的时间困扰, 就是把 byte 包装成字符串进行处理。而对于有限的 byte 类型而言,RLE 和字典 编码性能都特别好,后者性能要略优于前者。但是其编码解码时间太拖后腿了, 对于只需要一次加载而需要多次查询的一般情况而言,这也是不适合的。 3) 在更好优化字典编码的编码解码时间之前,RLE 编码是一个相对不错的选择。 如何更好的优化字典编码的编码解码时间是一个关键问题。
  • 18. 中国科学院计算技术研究所先进计算机系统实验室 18 5. 编码展望 截止到现在,我们所做的所有测评分析都是已经成型的编码算法,我们也发现了这些编 码存在的一些可以改进的地方,比如说针对 byte 类型编码采用的把 byte 包装成字符串的这 种耗时的处理,对字典本身采用增量位编码的编码方式,把 ORC 的 RLE 编码和位编码更好 的结合起来,让 Parquet 的 RLE 编码支持对等差数列的编码,合理的设置位编码,增量编码 的基本编码粒度。除了对现有的编码方式的内部进行优化之外,也可以考虑组合出更加高效 的编码方式。比如说把google protobuffer 编码结合ORC的RLE,字典编码结合增量编码等。 对于如何依据值分布情况采用最佳编码,核心是统计出值的分布情况,而不需要有用户 认为辨别。在数据加载的时候实现数据统计功也是以后需要考虑的一个方向。在决定采用那 种编码压缩方式的时候,需要权衡压缩比,编码时间,解码时间的比重,如何能得出一个较 为合理的量化公式也是可以考虑的一个方向。 参考文献 1. https://github.com/Parquet/parquet-format/blob/master/Encodings.md#run-length-encoding--b it-packing-hybrid-rle--3 2. http://docs.hortonworks.com/HDPDocuments/HDP2/HDP-2.0.0.2/ds_Hive/orcfile.html 3. http://code.google.com/p/protobuf/ 4. http://lemire.me/blog/archives/2012/03/06/how-fast-is-bit-packing/ 5. http://lemire.me/blog/archives/2012/04/05/bit-packing-is-fast-but-integer-logarithm-is-slow/ 6. http://lemire.me/blog/archives/2012/10/23/when-is-a-bitmap-faster-than-an-integer-list/ 7. http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog 8. http://lemire.me/blog/archives/2009/11/13/more-database-compression-means-more-speed-rig ht/ 9. http://lemire.me/blog/archives/2012/02/08/effective-compression-using-frame-of-reference-an d-delta-coding/ 10. http://en.wikipedia.org/wiki/Vectorization_(parallel_computing) 11. http://lemire.me/blog/archives/2012/09/12/fast-integer-compression-decoding-billions-of-inte gers-per-second/