数据文件的性能优化包含文件格式、压缩方式以及数据存储等三个方面。
- 文件格式
Hive 支持TEXT FILE, SEQUENCE FILE, AVRO, RC FILE, ORC和PARQUET等6种文件格式。HQL用来指定文件格式的命令为:
- CREATE TABLE ... STORE AS <file_format>: 创建表时指定文件格式
- ALTER TABLE ... [PARTITION partition_spec] SET FILEFORMAT <file_format>: 修改已存在表或者分区的文件格式(仅定义)。
指定表创建时的缺省文件格式
hive.default.fileformat = <file_format>
指定内部表创建时的缺省文件格式
hive.default.fileformat.managed = <file_format>
TEXT, SEQUENCE 和 AVRO文件是基于行的文件存储格式,即使只查询一列,整行会被读取。RCFILE,ORC 和 PARQUET文件是基于行列方式存储的文件格式,在这一方面有性能优势。
1.1 TEXTFILE 缺省文件格式,可以切分为若干部分平行处理。也可以适用GZip,LZO和Snappy算法压缩存放。不过,压缩过的文件不能切分平行处理。压缩文件的最佳适用时机是文件不太大,且接近2-3个HDFS block的大小。
1.2 SEQUENCEFILE 键值对数据的二进制存储格式。优势是相比文本文件占用空间小,适合作为MapReduce的输出文件格式。可以压缩之记录或者Block块级别,这里块级别压缩有更高的压缩比。开通Block块级别压缩可以通过设置:
set hive.exec.compress.output=true;
set io.seqfile.compression.type=BLOCK;
1.3 AVRO 二进制文件格式。另外这个文件格式是一个序列化和反序列化的框架。该文件格式把数据和数据模式(Schema)存放在一起,该数据模式(Schema)用来描述数据结构以方便处理其变化,如增删改数据列。由于这个特性,AVRO非常适合用来映射源数据。
1.4 RCFILE Record Columnar File。该文件格式是存放二进制键值对的平面文件,和序列文件类似。 该文件格式把数据平分成多个行组,一个或多个行组放在一个HDFS文件中,然后该文件格式把行组数据按列来存放。该文件格式可以切分,这样Hive在处理数据时可以很便捷地处理相关数据。
1.5 ORC 为Optimized Row Colummar简写。自Hive 0.11.0后支持,为RCFILE格式的优化版。缺省块大小为256M( RC FILE的块大小为4M,SEQUENCEFILE的块大小为1M),为了更大吞吐且涉及更少文件,优化了HDFS上的大量数据的序列度,减少Name Node上的负载。RCFILE需要通过Metastore来获取数据类型,而ORC通过适用特定编码器来基于数据类型优化压缩方式。另外这个文件格式把各数据列的基本统计数据(如最值、合计、记录数),以及轻量级的索引保存起来。
1.6 PARQUET 和ORC类似。该文件格式比ORC在Hadoop生态中有更广泛的支持。ORC主要被Hive, Pig 和 Spark等组件支持。PARQUET支持业界推荐的嵌套结构数据类型。自Hive 0.10.0,PARQUET通过插件在Hive中支持,自0.13.0后在Hive中原生支持。
取决于技术栈的组成,如果Hive是主要的定义和处理数据工具,推荐适用ORC;如果除了Hive还有别的数据处理工具,为了适应性考虑,使用PARQUET文件格式更佳。
1.7 Hadoop Archive File (HAR) 用于把HDFS文件归档。用于把大量小文件存放在HDFS中。弊端是,这些文件不可切分并且有兼容性问题。
- 压缩
Hive中,通过压缩中间数据和最终输出数据,可以大大降低在Mappers和Reducers之间数据传输量,从而让查询有更好的性能表现。我们可以通过命令行设置或者配置文件hive-site.xml的更改来压缩中间数据文件,
SET hive.exec.compress.intermediate=true
常用支持压缩编码算法为
Compression | Codec | Extension | Splittable |
---|---|---|---|
Deflate | org.apache.hadoop.io.compress.DefaultCodec | .deflate | N |
Gzip | org.apache.hadoop.io.compress.GzipCodec | .gz | N |
Bzip2 | org.apache.hadoop.io.compress.BZip2Codec | .gz | Y |
LZO | com.apache.compression.lzo.LzopCodec | .lzo | N |
LZ4 | org.apache.hadoop.io.compress.Lz4Codec | .lz4 | N |
Snappy | org.apache.hadoop.io.compress.SnappyCodec | .snappy | N |
Deflate压缩算法,缺省压缩算法,在高压缩比和CPU消耗之间取得平衡。
Gzip压缩算法,高压缩比,高CPU消耗
Bzip2压缩算法, 可切分,高CPU消耗,高耗时
LZO压缩算法,原生不可切分,通过预处理建索引切分文件
考虑到高CPU消耗和高压缩比的平衡,LZ4 或者Snappy压缩算法比缺省Deflate算法好,Snappy更流行。由于大多数压缩文件不可切分,不建议压缩单一大文件。最好是,把压缩文件生成一组HDFS文件块以方便每一文件只需花费较少时间来处理。
压缩算法可以通过mapred-site.xml,hive-site.xml或者命令行来指定,
SET hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec
中间数据压缩只对特定有多个MapReduce的job任务可以节省磁盘空间。为了进一步节省磁盘空间,Hive输出文件也可以压缩。可以通过hive-site.xml或者命令行来指定,
SET hive.exec.compress.output=true
SET mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.SnappyCodec
- 存储优化
经常被使用和扫描的数据被视为热数据(Hot Data)。热数据的查询性能对整体性能至关重要。增加热数据在HDFS的复制数据因子会大大增加该热数据可以被本地Job查询到。其实这是一种用空间来换时间的平衡策略。
$ hdfs dfs -setrep -R -w 4 /user/hive/warehouse/employee
Replication 4 set: /user/hive/warehouse/employee/000000_0
另外,过多的文件和数据冗余会导致Name Node的内存吃紧,尤其是有大量小于HDFS块大小的小文件情况。为了解决该问题,有以下途径,
- Hadoop Archive/ HAR
- SEQUENCEFILE 可以把小文件压缩成大一些的文件。
- CombineFileInputFormat: 在处理数据前,把小文件合并。
- HDFS Federation: 支持多个Name Node 来管理更多文件
别的方法有:
- HBase 有更小的Block大小和更好的文件格式来处理小文件存储和访问问题
- Flume NG 用来作为一个管道合并小文件为大文件
- 开发和调度文件合并程序来合并HDFS上的小文件或者在加载至HDFS前就完成合并
对Hive来说,以下配置可以把查询结果合并来避免生成小文件: - hive.merge.mapfiles 缺省为true
- hive.merge.mapredfiles 缺省为false
- hive.merge.size.per.task 缺省为256,000,000
- hive.merge.smallfiles.avgsize 出发合并操作的阈值,缺省为 16,000,000