Hive优化_1. 数据文件优化篇

来源:互联网 发布:长郡 雅礼 知乎 编辑:程序博客网 时间:2024/06/07 16:34

之前转载了一篇<Hive - 数据仓库的性能优化>。博主总结的很不错。这里本人将自己平时积累的资料汇总了一下,来补充一下这篇文章:

针对方法上篇的优化方法1,2,3 主要建立在 Hive 触发了一个 MapReduce Job。但是我们都知道,启用 MapReduce Job 会消耗系统开销的(从我这篇博文 Hive_4.DDL -- 数据库&内部表&外部表 可以发现当使用 Like 关键词的时候效率比 CTAS 要快很多倍)。对于这个问题, Hive 从0.10.0 版本开始,对于简单的不需要聚合操作的语句将不会触发 MapReduce Job,直接通过 Fetch task 来获取数据。
详细信息可以参考:http://blog.csdn.net/an342647823/article/details/21230033

1. 数据文件优化:

数据文件的优化包含了通过数据文件格式, 压缩,存储方式的选择来进行性能提升。

1.1 文件格式  -- 具体应用实例请参考: Hive_1. 数据存储 & 压缩

Hive 最新发布的 0.14.0 版本中支持TEXTFILESEQUENCEFILERCFILEORCPARQUET 和 Avro文件格式。我们可以通过以下方法来指定文件的格式:

  • CREATE TABLE ... STORE AS <File_Format>
  • ALTER TABLE ... [PARTITION partition_spec] SET FILEFORMAT <File_Format>
  • SET hive.default.fileformat = <File_Format> --设置表的默认文件格式

在这里,<File_Type> 可以是 TEXTFILESEQUENCEFILERCFILEORCPARQUET 或者 Avro 类型.
我们可以通过 TEXTFILE 格式将 text 文件直接加载到一张表中。如果要往表中加载其他格式的数据,我们需要将数据先加载成 TEXTFILE 格式的表,之后再使用  INSERT OVERWRITE TABLE <target_file_format_table> SELECT * FROM <text_format_source_table> 语句进行转换,将期望的数据格式加载到表中。

Hive 支持如下数据格式,它们的优化如下所示:

  • TEXTFILE :这是 Hive 默认的文件格式。文本文件中的数据没有被压缩,所以我们可以通过压缩工具( GZip, Bzip2, Snappy) 对它进行压缩。但是 Gzip 和 Snappy 压缩的文件是不可分割的,这就导致了处理一个大文件时需要一个单独的,耗资源的 map job 。增加了系统的负担和时间。这里需要注意的是,Bzip2 从 Hadoop 2.1 开始才支持本地可分割。所以你会发现网上很多文章都把 Bzip2 认为是不可分割的。我将会在之后的 Hadoop  Compression 专题中详细介绍。详细参考 Jira ticket : https://issues.apache.org/jira/browse/HADOOP-8462
  • SEQUENCEFILE:这是一个基于键值对的二进制存储格式。它是优势是 SequenceFile 比文本文件更加紧凑,同时能够很好的兼容 MapReduce 的输出格式。SequenceFile 有3中压缩方式:Record & Block & Null。 你可以通过以下方式来启动 Blcok 级别的压缩:

jdbc:hive2://> SET hive.exec.compress.output=true; jdbc:hive2://> SET io.seqfile.compression.type=BLOCK; 
不幸的是,文本文件和 SequenceFile 都是基于行级别的存储文件格式,对Hive 来说并不是最优的选择。由于 Hive 每次都需要读取整行数据,尽管只需要一列数据。因此 RCFile , ORC, Parquet 便应运而生了。它们用来解决文本文件和 SequenceFile所存在的限制。(这里需要了解一下  Avro 也是基于行的存储,由于在 Avro 系列中已经做了详细介绍,这里就不对 Avro 过多阐述了)

  • RCFile :它是柱状记录文件(Record Columnar File)的简称。它是一个由二进制键值对组成的平面文件,与SequenceFile 有点相似。RCFile 是基于行组(row group)的水平数据分割。这里一个或者多个行组是 HDFS 中存储的文件。RCFile 通过首先将每一行的第一列来将行组数据保存为柱状格式,之后再对每一行的第二列,。。。这种格式是可分割的并且允许 Hive 跳过无关数据来更快更轻松得到数据结果。
  • ORC :它是 Optimized Row Columnar的简写。从 Hive 0.11.0 版本才开始支持 ORC 格式。ORC 用来解决 RCFile部分性能问题。它提供了默认的 256MB 大小的 blcok ( RCFile 是 4MB, SequenceFile 是1MB)来对NameNode 节点上的高吞吐量和通过更少的 reducer端需要处理的文件来优化HDFS 中序列化文件的读取。与 RCFile 不同的是,ORC 需要依赖元数据来确认数据类型。它通过特定的编码器来识别数据类型,这样它就能根据不同类型进行压缩优化。ORC 同样支持基本列的统计方法:MINMAXSUM, 和 COUNT.以及使用一个轻量级的索引来跳过无关的行块。
  • Parquet :它是一个类似于 ORC 格式的行柱状文件格式。不同的是,相比较只支持 Hive 和 Pig 的ORC 格式,Parquet 在 Hadoop 生态系统中已经广泛支持许多项目。Parquet 利用 Google的最佳实践案例:Dremel 来支持嵌套的结构化数据。Parquet 支持从 Hive 0.10.0 版本开始就可以作为一个插件进行使用,知道 Hive 0.13.0 才开始得到本地支持。(Avro 是从 Hive 0.14 版本才得到本地支持)。
Google Dremel high level intruduce:http://research.google.com/pubs/pub36632.html
Google Dremel 原理(中文):http://www.yankay.com/google-dremel-rationale/

考虑到 Hive 的成熟度,还是建议在你的 Hadoop 环境中使用 ORC 格式作为主要的工具。如果你的 Hadoop 生态系统中使用多种 tools, Parquet 在适应性方面不失为一个更好的选择。

注意:Hadoop Archive File (HAR) 是HDFS 中另一种打包文件的格式。它对HDFS中大量的小文件存储是可选的(并不是很好的选择)。由于将大量的小文件直接存储是非常低效的。HAR 目前仍然有以下的一些限制使得它无法出众:不可分割,兼容性比较差。更多关于 HAR 信息请参考维基百科:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Archiving.

1.2 压缩

为 Mapper 和 Reducer 中间数据和HDFS结果数据选择合适的压缩格式,在Hive 中能够明显的减小磁盘的 I/O,以至于Hive 查询也会有更好的性能。为了对 Hive 通过 MapReduce job 处理的文件进行压缩,我们需要通过 Hive CLI 或者 hive-site.xml 文件来设置以下属性(默认情况是 false ):

jdbc:hive2://> SET hive.exec.compress.intermediate=true

接下来,我们就需要考虑应该配置哪一种压缩编码,Hadoop 和 Hive 中支持的通用压缩编码器如下所示:

压缩方式

编码方式

拓展名

可分割

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.hadoop.compression.lzo.LzopCodec

.lzo

N

LZ4

org.apache.hadoop.io.compress.Lz4Codec

.lz4

N

Snappy

org.apache.hadoop.io.compress.SnappyCodec

.snappy

N

Hadoop 有一个默认压缩编码器(.deflate),压缩率和 CPU 成本都比 GZip 要高。Bzip2 是可分割的,但是直到 Hadoop 1.1 才支持分割(参考 Jira ticket :https://issues.apache.org/jira/browse/HADOOP-4012)。Bzip2 也由于高额的 CUP 开销使得压缩很缓慢。
LZO 文件并不是本地可分割,但是我们可以通过 com.hadoop.compression.lzo.LzoIndexer 创建一个索引来决定文件的分割,它很好的中和了CUP开销和压缩率(在后面会有专题介绍该内容)。LZ4 和 Snappy能够很好的处理一个 Job。
由于很多编码方法不支持压缩后可分割,所以不建议在 HDFS 中压缩大文件。 
你可以通过  mapred-site.xmlhive-site.xml 或者 Hive CLI 来指定压缩编码器,如下所示:

jdbc:hive2://> SET hive.intermediate.compression.codec=
. . . . . . .> org.apache.hadoop.io.compress.SnappyCodec

对指定的 Job 中间数据的压缩只会节省磁盘空间,但是需要多个 map 和 reduce job。为了进一步节省磁盘空间,Hive 的输出文件是可以被压缩的。可以通过设置  hive.exec.compress.output 属性为 true. Hive 可以通过配置 mapred.map.output.compression.codec 属性来对中间数据进行压缩。你可以从 hive-site.xml 文件进行设置,或者在 Hive CLI 设置。

jdbc:hive2://> SET hive.exec.compress.output=true
jdbc:hive2://> SET mapred.output.compression.codec=
. . . . . . .> org.apache.hadoop.io.compress.SnappyCodec

1.3 存储优化

对于频繁用于扫描的数据,我们会称之为 Hot data。通常,对于hot data 的查询对整体性能来说是至关重要的。增加 hot data 在 HDFS 中的副本因子可以增加Hive job 本地查找命中率并且能够提高性能。这同样是衡量存储的一个方面:

$ hdfs dfs -setrep -R -w 4 /user/hive/warehouse/employeeReplication 4 set: /user/hive/warehouse/employee/000000_0

另一方面,太多的文件或者冗余会耗尽NameNode 的内存,特别的对于大量的小于 Hadoop blcok 大小的文件。Hadoop 对于处理大量小文件问题的这种情况已经提出了解决方案。如下所示:

  • Hadoop Archive and HAR用来打包小文件的工具集.
  • SequenceFile format : 将小文件压缩成大文件的一种格式.
  • CombineFileInputFormat   一种在map 和 reduce 进程前整合小文件的输入格式。是 Hive 的默认 InputFormat ( 参考:https://issues.apache.org/jira/browse/HIVE-2245)。
  • HDFS federation :它允许 NameNode 有更好的扩展性并且能够管理多个文件。

我们同样可以使用 Hadoop 生态系统中的其他工具来处理(在已经安装该工具的前提下),如下所示:

  • HBase 有更小的 block 大小和文件格式来处理小文件处理问题。
  • Flume NG 可以用来作为将小文件整合成大文件的管道( 关于 Flume-NG 请参考:http://blog.csdn.net/mike_h/article/details/50146955)
  • 通过离线的文件整合程序来将 HDFS 中小文件整合到一起。

对 Hive 来说,我们可以通过配置属性来将查询结果进行整合,避免创建小文件:

  • hive.merge.mapfiles: 将在只有 map 的job 中整合小文件,默认为 true.
  • hive.merge.mapredfiles: 在 MapReduce Job 最后进行整合小文件,可以设置为 true , 默认是 false.
  • hive.merge.size.per.task: 该属性定义了对于每个任务运行整合的文件最大值。默认是 256,000,000.
  • hive.merge.smallfiles.avgsize: 这是用来触发文件整合操作的阈值,默认是16,000,000.

当输出文件的平均大学都小于指定的 hive.merge.smallfiles.avgsize 值,并且hive.merge.mapfiles 和 hive.merge.mapredfiles 都设置为true,Hive 会启动一个额外的 MapReduce Job 来整合输出文件为一个大文件。


0 0
原创粉丝点击