在新建Hive表时,可以使用stored as rcfile来指定hive文件的存储方式为RCFile。
一、RCFile文件结构
下图是一个RCFile的文件结构形式。
从上图可以看出:
1)一张表可以包含多个HDFS block。
2)在每个block中,RCFile以行组(row group,类似于ORC中的stripe)为单位存储其中的数据。所谓行组是指在关系型数据块中,若干条记录组成的一个group。对于一张表来说,row group的大小是固定的。通过HDFS的block大小和row group的大小,能够确定一个block上可以容纳多少个row group。
3)row group又由三个部分组成,包括一个用于在block中分隔两个row group的16字节的标志区,一个存储row group元数据信息的header,以及实际数据区。表中的实际数据以列为单位进行存储。
二、RCFile压缩方式
在存储RCFile时,会对每个row group的metadata header区和data区进行压缩。
在metadata header区中,记录了该row group中有多少记录,每个column总共有多少字节数,以及每个column中每一个field的字节数等信息。对metadata header区,使用RLE(Run Length Encoding)算法来压缩数据。需要读取指定column的记录时,可以根据这个metadata中记录的字节数等信息,很快定位到对应的数据。
对data区的数据压缩时,RCFile文件格式并不会将整个区域一起进行压缩,而是以列为单位进行Gzip压缩,这样的处理方式使得需要读取某些指定列的数据时,其他无关的列不需要进行读取。
三、RCFile的数据写入方式
由于目前HDFS只支持在文件末尾追加内容,无法随意修改hdfs文件中的数据。所以在使用RCFile文件的hive表中也只能在文件末尾写入新的记录。在向RCFile写入数据时,
(1)为了避免频繁的写入操作,RCFile会为每一个column在内存中维持一个对应的column holder。当有记录插入到hive表中时,会把这一条记录的每个字段拆散存入到对应的column holder的末尾。伴随着这个操作的同时,会在metadata header中记录此次操作的相关信息。
(2)上面的column holder当然是不能无限大的,为此RCFile设定了两个参数,当满足任何一个时,就会把column holder中的数据flush到磁盘上。这两个参数一个是写入记录数,另一个是column holder使用的内存大小。
(3)记录写入完毕后,RCFile首先会将metadata header进行压缩。然后把每一个column单独进行压缩,最后将压缩好的数据flush到同一个row group中。
四、RCFile的数据读取和解压缩方式
当需要从一个row group读取数据时,RCFile并不会将整个row group中的数据都读入到内存中,需要读入的数据只包括metadata header,以及在语句中指定的那些column。
这两部分数据读入到内存中后,首先会将metadata header进行解压缩,并一直保存在内存中。接下来对加载到内存中的column数据,在RCFile中有一个lazy decompression的概念,这个的意思是说,column数据并不会在加载到内存中后马上进行解压缩,而是后续处理中的确需要读取这个column数据时解压缩过程才会执行。比如有一个sql语句,select a,b,c from table where a > 5;
首先会对字段a解压缩,如果判断所有记录中没有a > 5的记录,那么字段b和字段c都不必要进行解压缩了。
五、RCFile的相关参数
参数 | 默认值 | 描述 |
---|---|---|
hive.io.rcfile.record.buffer.size | 4194304 | 设置row group的大小 |
hive.io.rcfile.record.interval | 2147483647 | row group中最大记录数 |
row group默认大小为4MB主要是因为row group不能太大,也不能太小。在Gzip压缩算法中,增大row group的大小能够提升压缩的性能。但是当row group的大小达到某个阈值时,继续增大row group并不能带来压缩性能的提升。并且,以上面的sql语句为例如果一个row group越大,其中保存的记录也就越多,这样该row group中出现a >5的记录的概率就越大,那么就越难使用到lazy decompression这一特性带来的性能提升。并且row group越大,消耗的内存也就越多。
这个大小限制在ORC文件格式中得到了改善。