上篇文章从整体介绍了Orcfile的存储格式,接下来重点介绍下Orc里用到的几种编码格式:
字典编码:用于String类型的字段
Run-Length编码:用于int,long,short等类型的编码
Bit编码:可以用于各种数据类型
1,字典编码:
对于String类型的每个字段分别保存一个字典,记录每个值在字典中的位置,保存字典的数据结构采用一棵红黑树。对于每个String字段,最终会有三个输出Stream,分别是StringOuptut(记录字典中的值),LengthOutput(记录每个字典值的长度),RowOutput(记录字段在字典中的位置)。
思考1:为什么要用红黑树?
因为红黑树无论是插入,删除,查找的性能都比较平均,都是O(logN),而且是平衡查找树,最坏情况也不会退化成O(N)
思考2:其实一般存储时还会使用LZO之类的压缩,它们本身就是一种字典压缩,为什么Orc里面要自己做字典压缩?
因为LZO之类的压缩窗口一般比较小(LZO默认是64KB),而Orc的字典压缩是以整个字段为范围来压缩的,压缩率会更好。
2,Run-Length编码:
对于int,long,short类型的字段,使用Run-Length编码。该Run-Length能够对等差数列(完全相等也属于等差数列)进行压缩,该等差数列需要满足以下两个条件:
1,至少包含3个元素
2,差值在-128~127之间(因为差值用1Byte来表示)
对于不满足等差数列的数字,Run-Length编码也能存储,但是没有压缩效果,Run-Length的具体存储如下:
第一个Byte是Control Byte,取值在-128~127之间,其中-1~-128代表后面存储着1~128个不满足等差数列的数字,0~127代表后面存储着3~130个等差数列的数字;
如果Control Byte>=0,则后面跟着一个Byte存储差值,否则不存储该Byte;
如果Control Byte>=0,则后面跟着等差数列的第一个数,否则跟着-Control Byte个数字。
例子:
原始数字:12,12,12,12,12,10,7,13
经过Run-Length的数字:2,0,12,-3,10,7,13
红色代表Control Byte,黄色代表差值,黑色代表具体的数字。
3,Bit编码:
对所有类型的字段都可以采用Bit编码来表示该值是否为null。在写任何类型字段之前,先判断该字段值是够为null,如果为null则bit值存为0,否则存为1,对于为null的字段在实际编码时不需要存储了。经过Bit编码之后,可以对于8个bit组成一个Byte,再对其进行Run-Length编码。
其实除了这三种编码格式之外,Orc对于hive的复杂类型array,map,list等,将其降维成基本类型来存储,这个也是值得借鉴的,如果有空之后会进行分析。