1.为啥Hive需要优化?
(1)Hive的执行依赖于底层的MapReduce作业,因此对Hadoop作业的优化或者MapReduce作业的调整是提高Hive性能的基础。
(2)如果没有经过优化调整的Hive,那么很容易出现:即使查询hive中的一个小表,有时也会耗时数分钟或几十分钟才能得到结果,甚至很难得到结构,直接被卡死了。
(3)Hive对于OLAP类型的应用有很大的局限性,它不适合需要立即返回查询结果的场景。
忍不住了,要吐槽一下。在此笔者认为,hive本身只是一个上层应用上的执行类数据库的某些语句而已,造成hive某些性能上的问题,其根本还是hadoop自身设计上的问题,
是其设计上存在缺陷造成了不适合于对实时性要求很高的应用。那种说hadoop只适合于大数据、批量、非实时性的应用,这只是为了掩盖其本身的缺陷,诓骗世人的说辞。
至少笔者认为Hadoop是存在设计上的缺陷的,设计上的缺陷造成了对实时性要求高——低时延的应用支持不足,以及hive对事务上的支持不足。
笔者是不认可CAP理论的,这个理论听起来似乎有道理,而且说的是客观事实,但实际上造成这一客观事实的源头,却正是Hadoop本身设计上的缺陷所导致的,
它无法克服和解决掉所存在的问题。笔者只是在此略微吐槽一下,只是给偶来之观众以思维上的启迪。
在笔者没有搞出新的大数据管理软件,取代Hadoop这类工具之前,该学习别人的还是要学习的,何况乎笔者也是学习者之一。笔者虽对其有微词,但也认可其中诸多优秀的设计理念,值得学习。
2.Hive优化方式:
2.1参数优化
2.1.1启用压缩
启用压缩可以使得磁盘上存储的数据所占用空间变小,这样可以使得I/O负载率降低进而提高查询速度。
压缩和解压会消耗CPU资源,但Hive产生的MapReduce作业往往是I/O密集型的,通常CPU开销不是问题,而内存空间才是问题的关键。
一个复杂的Hive查询在提交后,通常被转换为一系列中间阶段的MapReduce作业,Hive引擎将这些作业串联起来完成整个查询。因此可以将这些中间数据进行压缩。
这些中间数据是指上一个MapReduce作业的输出,这些输出将被下一个MapReduce作业作为输入数据使用。
(1)查看Hive支持的压缩编码方式:set io.compress.codes,示例如下:
(2)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.exec.compress.intermediate | false | true | 该参数用于启动MapReduce中间数据压缩。 该参数值设置为“true”,即表示启用中间结果压缩。 |
hive.intermediate.compression.codec | 空值 | org.apache.hadoop.io.compress.SnappyCodec | 该参数设置压缩格式。可支持参数值如下: org.apache.hadoop.io.compress.SnappyCodec org.apache.hadoop.io.compress.GzipCodec org.apache.hadoop.io.compress.BZip2Codec org.apache.hadoop.io.compress.DeflateCodec org.apache.hadoop.io.compress.Lz4Codec org.apache.hadoop.io.compress.DefaultCodec |
hive.intermediate.compression.type | 空值 | BLOCK | 该参数设置为“BLOCK”,即数据以区块进行压缩。 |
hive.exec.compress.output | false | true | 该参数设置Hive输出写入到表中是,对输出内容进行压缩。 参数值设置为“true”,即表示启用最终输出压缩。 |
(3)参数文件配置:
1)启用中间结果压缩参数配置示例(推荐该种方式必须设置):
<property>
<name>hive.exec.compress.intermediate</name>
<value>true</value>
<description>
This controls whether intermediate files produced by Hive between multiple map-reduce jobs are compressed.
The compression codec and other options are determined from Hadoop config variables mapred.output.compress*
</description>
</property>
<property>
<name>hive.intermediate.compression.codec</name>
<value>org.apache.hadoop.io.compress.SnappyCodec</value>
<description/>
</property>
<property>
<name>hive.intermediate.compression.type</name>
<value>BLOCK</value>
<description/>
</property>
2)启用最终结果压缩示例(须同时设置压缩格式和数据块压缩)
<property>
<name>hive.exec.compress.output</name>
<value>true</value>
<description>
This controls whether the final outputs of a query (to a local/HDFS file or a Hive table) is compressed.
The compression codec and other options are determined from Hadoop config variables mapred.output.compress*
</description>
</property>
注:参数文件中,压缩格式设置和数据块压缩,只需要设置一次即可。
2.1.2优化连接
(1)自动Map连接
当一个大表和一个小表进行连接时,配置自动Map连接是一个非常有用的特性。若启用该特性,则小表将保存在每个节点的本地缓存中,并在Map阶段与大表进行连接。
开启自动Map连接提供了两个好处:
第一,将小表装进缓存将节省每个数据节点上的读取时间;
第二,避免了Hive查询中的倾斜连接,每个数据块的连接操作已经在Map阶段就完成了。
1)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.auto.convert.join | true | true | 该参数用于是否启用基于输入文件的大小,将普通连接转化为Map连接的优化机制。 该参数默认是开启的。 |
hive.auto.convert.join.noconditionaltask | true | true | 该参数用于是否启用基于输入文件的大小,将普通连接转化为Map连接的优化机制。 假设参与连接的表(或分区)有N个,如果打开这个参数,并且有N-1个表(或分区)的大小总和小于hive.auto.convert.join.nonconditionaltask.size参数设定的值,那么会直接将连接转化为Map连接。 该参数默认也是开启的。 |
hive.auto.convert.join.noconditionaltask.size | 10000000 | 10000000 | 若hive.auto.convert.join.noconditionaltask是关闭的,该参数不起作用。 否则,如果参与连接的N个表(或分区)中的N-1个总大小小于该参数的值,那么则直接将连接转化为Map连接。 该参数默认值为10MB。可根据实际情况进行调整。 |
hive.auto.convert.join.use.nonstaged | false | true | 该参数用于对于条件连接时,如果从一个小的输入流可以直接应用于join操作而不需要过滤或者投影,那么不需要通过MapReduce的本地任务表在分布式缓存中预存。 该参数在vectorization或tez执行引擎中不工作。 该参数默认是不开启的。 |
2)参数文件配置:
启用自动Map连接参数配置示例:
<property>
<name>hive.auto.convert.join</name>
<value>true</value>
<description>Whether Hive enables the optimization about converting common join into mapjoin based on the input file size</description>
</property>
<property>
<name>hive.auto.convert.join.noconditionaltask</name>
<value>true</value>
<description>
Whether Hive enables the optimization about converting common join into mapjoin based on the input file size.
If this parameter is on, and the sum of size for n-1 of the tables/partitions for a n-way join is smaller than the
specified size, the join is directly converted to a mapjoin (there is no conditional task).
</description>
</property>
<property>
<name>hive.auto.convert.join.noconditionaltask.size</name>
<value>10000000</value>
<description>
If hive.auto.convert.join.noconditionaltask is off, this parameter does not take affect.
However, if it is on, and the sum of size for n-1 of the tables/partitions for a n-way join is smaller than this size,
the join is directly converted to a mapjoin(there is no conditional task). The default is 10MB
</description>
</property>
<property>
<name>hive.auto.convert.join.use.nonstaged</name>
<value>true</value>
<description>
For conditional joins, if input stream from a small alias can be directly applied to join operator without
filtering or projection, the alias need not to be pre-staged in distributed cache via mapred local task.
Currently, this is not working with vectorization or tez execution engine.
</description>
</property>
(2)倾斜链接
当两个大表连接时,会先基于连接键分别对两个表进行排序,然后对他们进行连接。Mapper将特定键值的所有行发送给同一个Reducer。
例如:对A表和B表进行连接,表A的id列有1、2、3、4四个值,而B表id列有1、2、3三个值,现有查询语句如下:
select A.id from A join B on A.id=B.id
上述语句,则会产生一系列的Mapper读取表中的数据并基于键值发送给Reducer。如id=1行进入Reducer R1,id=2的行进入Reducer R2, id=3的行进入Reducer R3,id=4的行进入Reducer R4。
这些Reducer进一步产生A、B的交集并输出。其中Reducer R4只从A中获取行,不会产生查询结果。
现假设id=1的数据行是高度倾斜的,则R2和R3会很快完成,而R1需要很长的时间,将称为整个查询的瓶颈。因此配置倾斜连接的相关属性可以优化倾斜连接。
1)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.optimize.skewjoin | false | true | 该参数用于是否为连接表中的倾斜键创建单独的执行计划。 它是基于存储在元数据中的倾斜键。 在编译时,Hive为倾斜建和其他键值生成各自的查询计划。 该参数默认是开启的。 skewjoin的原理: 1)对于skewjoin.key,在执行job时,将它们存入临时的HDFS目录中,其他数据正常执行。 2)对于倾斜数据开启map join操作,对非倾斜值采取普通join操作。 3)将倾斜数据集和非倾斜数据集进行合并操作。 |
hive.skewjoin.key | 100000 | 100000 | 该参数决定如何确定连接中的倾斜建。 在连接操作中,如果同一键值所对应的数据行数超过该参数值,则认为是一个倾斜连接键。 |
hive.skewjoin.mapjoin.map.tasks | 10000 | 10000 | 指定倾斜连接中,用于Map连接作业的任务数。 该参数应该与hive.skewjoin.mapjoin.min.split一起使用,执行细粒度的控制。 |
hive.skewjoin.mapjoin.min.split | 33554432 | 33554432 | 通过指定最小split的大小,确定Map连接作业的任务数。 该参数应该与hive.skewjoin.mapjoin.map.tasks一起使用,执行细粒度的控制。 |
hive.optimize.skewjoin.compiletime | false |
true | 该参数用于开启数据倾斜的join编译时优化。 基于存储在元数据中的倾斜key,在编译时给导致倾斜的key单独创建执行计划,而其他key采用另外的执行计划进行join。然后对生成的两个join执行后求并集。因此除非相同的倾斜key同时存在于这两个join表中,否则会引起倾斜的key在join就会优化map-side join。 该参数与hive.optimize.skewjoin主要区别在于,该参数存储在metastore中的倾斜信息在编译时优化执行计划。如果元数据中没有倾斜信息,则此参数无效。 如果建表语句元数据中指定了skew key,该参数开启则开启了skew join。 该参数默认未开启,但推荐开启 。 |
2)参数文件配置:
启用倾斜连接优化参数配置示例:
<property>
<name>hive.optimize.skewjoin</name>
<value>true</value>
<description>
Whether to enable skew join optimization.
The algorithm is as follows: At runtime, detect the keys with a large skew. Instead of processing those keys, store them temporarily in an HDFS directory.
In a follow-up map-reduce job, process those skewed keys.
The same key need not be skewed for all the tables, and so,the follow-up map-reduce job (for the skewed keys) would be much faster, since it would be a map-join.
</description>
</property>
<property>
<name>hive.optimize.skewjoin.compiletime</name>
<value>true</value>
<description>
Whether to create a separate plan for skewed keys for the tables in the join.
This is based on the skewed keys stored in the metadata. At compile time, the plan is broken into different joins: one for the skewed keys,
and the other for the remaining keys.
And then,a union is performed for the 2 joins generated above.
So unless the same skewed key is present in both the joined tables, the join for the skewed key will be performed as a map-side join.
The main difference between this parameter and hive.optimize.skewjoin is that this parameter uses the skew information stored in the
metastore to optimize the plan at compile time itself.
If there is no skew information in the metadata, this parameter will not have any affect.
Both hive.optimize.skewjoin.compiletime and hive.optimize.skewjoin should be set to true.
Ideally, hive.optimize.skewjoin should be renamed as hive.optimize.skewjoin.runtime, but not doing so for backward compatibility.
If the skew information is correctly stored in the metadata, hive.optimize.skewjoin.compiletime would change the query plan to take
care of it, and hive.optimize.skewjoin will be a no-op.
</description>
</property>
<property>
<name>hive.skewjoin.mapjoin.map.tasks</name>
<value>10000</value>
<description>
Determine the number of map task used in the follow up map join job for a skew join.
It should be used together with hive.skewjoin.mapjoin.min.split to perform a fine grained control.
</description>
</property>
<property>
<name>hive.skewjoin.mapjoin.min.split</name>
<value>33554432</value>
<description>
Determine the number of map task at most used in the follow up map join job for a skew join by specifying
the minimum split size. It should be used together with hive.skewjoin.mapjoin.map.tasks to perform a fine grained control.
</description>
</property>
(3)桶Map连接
如果连接中存在桶表,即表是按特定列进行分桶的,那么可以开启桶Map连接提升性能。
1)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.optimize.bucketmapjoin | false | true | 该参数用于尝试桶Map连接。 该参数默认是关闭的。 |
hive.optimize.bucketmapjoin.sortedmerge | false | true | 该参数尝试在Map连接中使用归并排序。 该参数默认是关闭的。 |
2)参数文件配置:
启用桶Map连接优化参数配置示例:
<property>
<name>hive.optimize.bucketmapjoin</name>
<value>true</value>
<description>Whether to try bucket mapjoin</description>
</property>
<property>
<name>hive.optimize.bucketmapjoin.sortedmerge</name>
<value>true</value>
<description>Whether to try sorted bucket merge map join</description>
</property>
2.1.3更换计算执行引擎
Hive支持MR、Tez、Spark三种计算执行引擎,其中MR是默认的计算引擎,即使用MapReduce引擎。
通常使用tez和spark两种计算引擎性能都优于MR,但需要额外配置相关的参数和相应的工具安装、配置。
(1)使用Tez作为计算执行引擎
(2)使用Spark作为计算执行引擎
2.1.4启动并行执行
每条Hive语句的执行,都将被转化为一个或多个执行阶段,可能是一个MapReduce阶段、采样阶段、归并阶段、限制阶段等。
默认Hive在任意时刻只能执行其中一个阶段。如果组成一个特定作业的多个执行阶段是彼此独立的,那么他们就可以并行执行,从而使得整个作业得以更快速完成。
(1)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.exec.parallel | false | true | 该参数用于启动并行执行作业。 强烈建议开启。 |
hive.exec.parallel.thread.number | 8 | 10 | 该参数用于设置最多可以并行执行的作业数。 该值的设置应当根据CPU核数和线程数进行合理设置。 |
(2)参数文件配置:
启用桶Map连接优化参数配置示例:
<property>
<name>hive.exec.parallel</name>
<value>true</value>
<description>Whether to execute jobs in parallel</description>
</property>
<property>
<name>hive.exec.parallel.thread.number</name>
<value>10</value>
<description>How many jobs at most can be executed in parallel</description>
</property>
2.1.5控制并行Reduce任务
Hive通过将查询划分成一个或多个MapReduce任务达到并行的目的。确定最佳的mapper个数和reducer取决于多个变量,例如:输入的数据量,以及对这些数据执行的操作类型等。
如果有太多的mapper和reducer任务,会导致启动、调度和运行作业过程中产生过多的开销,而如果设置的数量太少,那么就可能没有充分利用好集群内在的并行性。
因此,对于一个Hive查询,Hive提供相应的参数可进行优化控制并行reduce任务的个数。
(1)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.exec.reducers.bytes.per.reducer | 256000000 | 256000000 | 该参数用于设置每个reducer的字节数。 Hive是按照输入的数据量大小来确定reducer个数的。例如输入1GB的数据,将使用4个reducer。 该参数默认值为256MB。 |
hive.exec.reducers.max | 1009 | 1009 | 该参数设置可能会使用的最大reducer个数。 |
(2)参数文件配置:
启用桶Map连接优化参数配置示例:
<property>
<name>hive.exec.reducers.bytes.per.reducer</name>
<value>256000000</value>
<description>size per reducer.The default is 256Mb, i.e if the input size is 1G, it will use 4 reducers.</description>
</property>
<property>
<name>hive.exec.reducers.max</name>
<value>1009</value>
<description>
max number of reducers will be used. If the one specified in the configuration parameter mapred.reduce.tasks is
negative, Hive will use this one as the max number of reducers when automatically determine number of reducers.
</description>
</property>
2.1.6启用向量化
Hive可通过查询执行向量化,使Hive从单行处理数据改为批量处理方式。具体来说是一次处理1024行而不是每次只处理1行。
这大大地提升了指令流水线和缓存的利用率,从而提高了表扫描、聚合、过滤和连接等操作的性能。
(1)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.vectorized.execution.enabled | true | true | 该参数用于开启查询执行的向量模式。 |
hive.vectorized.execution.reduce.enabled | true | true | 该参数用于开启查询执行reduce端的向量模式。 |
hive.vectorized.execution.reduce.groupby.enabled | true | true | 该参数用于开启查询执行reduce端group by操作的向量模式。 |
(2)参数文件配置:
启用桶Map连接优化参数配置示例:
<property>
<name>hive.vectorized.execution.enabled</name>
<value>true</value>
<description>
This flag should be set to true to enable vectorized mode of query execution.
The default value is true to reflect that our most expected Hive deployment will be using vectorization.
</description>
</property>
<property>
<name>hive.vectorized.execution.reduce.enabled</name>
<value>true</value>
<description>
This flag should be set to true to enable vectorized mode of the reduce-side of query execution.
The default value is true.
</description>
</property>
<property>
<name>hive.vectorized.execution.reduce.groupby.enabled</name>
<value>true</value>
<description>
This flag should be set to true to enable vectorized mode of the reduce-side GROUP BY query execution.
The default value is true.
</description>
</property>
2.1.7启用基于成本的优化器
Hive提供了基于的成本优化器(CBO),其特性是可以根据查询成本指定执行计划。
例如:确定表连接的顺序、以何种方式执行连接、使用的并行度等。
(1)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.cbo.enable | true | true | 该参数用于控制是否启用基于成本的优化器。 Hive的CBO使用Apache Calcite框架实现。 该参数默认是开启的。 |
hive.compute.query.using.stats | true | true | 该参数用于Hive在执行某些查询时,只需要利用元数据存储中保存的状态信息返回结果。 为了收集基本状态信息,需要将hive.stats.autogather参数值设为true。 为了收集更多的状态信息,需要运行analyze table查询命令。 |
hive.stats.autogather | true | true | 该参数用于开启表、分区的统计信息自动收集。 但是,对于一个新表或者分区,只有在执行INSERT OVERWRITE/INTO语句时,才会自动收集统计信息,执行LOAD操作时,不会自动收集统计信息。 该参数默认是开启的。 |
hive.stats.fetch.partition.stats | true | true | 该参数用于操作树种所标识的统计信息,需要分区级别的基本统计,如每个分区的行数、数据量大小和文件大小等 。分区统计信息从元数据存储中获取。 如果存在很多分区,要为每一个分区收集统计信息可能会消耗大量的资源。 这个标志可被用于禁止从元数据存储中获取分区统计。 当该标志设置为false时,Hive从文件系统获取文件大小,并根据表结构估算行数。 该参数已于Hive3.0.0开始,被移除了。 |
hive.stats.fetch.column.stats | false | true | 该参数用于操作树种所标识的统计信息,需要列统计。 列统计信息从元数据存储中获取。 如果存在很多列,要为每一个列收集统计信息可能会消耗大量的资源。 这个标识可被用于禁止从元数据存储中获取列统计。 该参数默认是关闭的,推荐将其关闭,即参数值为false。 |
(2)参数文件配置:
启用桶Map连接优化参数配置示例:
<property>
<name>hive.vectorized.execution.enabled</name>
<value>true</value>
<description>
This flag should be set to true to enable vectorized mode of query execution.
The default value is true to reflect that our most expected Hive deployment will be using vectorization.
</description>
</property>
<property>
<name>hive.vectorized.execution.reduce.enabled</name>
<value>true</value>
<description>
This flag should be set to true to enable vectorized mode of the reduce-side of query execution.
The default value is true.
</description>
</property>
<property>
<name>hive.vectorized.execution.reduce.groupby.enabled</name>
<value>true</value>
<description>
This flag should be set to true to enable vectorized mode of the reduce-side GROUP BY query execution.
The default value is true.
</description>
</property>
2.2语句优化
笔者认为下面涉及到语句优化方式很是鸡肋,但很重要,需要使用者注意和防范的。
2.2.1避免使用order by全局排序
Hive中使用order by子句实现全局排序。order by只用一个Reducer产生结果,对于大多数据集,这种做法效率很低。
如果不需要全局排序,则可以使用sort by子句,该子句为每一个reducer生成一个排好序的文件。
如果需要控制一个特定数据行流向哪个reducer,可以使用distribute by子句。
例子:
select id,name,salary,dept from employee distribute by dept sort by id asc,name desc;
即:属于一个dept的数据会分配到同一个reducer进行处理,同一个dept的所有记录按照id、name进行列排序。最终的结果集是全局有序的。
2.2.2优化limit操作
默认时limit操作是执行整个查询,然后返回限定的行数。但某些情况下,这种处理方式很是浪费,因此可以进行优化,hive提供了这样参数优化方式。
(1)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.limit.optimize.enable | false | true | 该参数用于是否启用limit优化。 当使用limit语句时,对源数据进行抽样。 该参数默认是关闭的。 |
hive.limit.row.max.size | 100000 | 100000 | 该参数用于在使用limit做数据的子集查询时保证的最小行数数据量。 |
hive.limit.optimize.limit.file | true | 10 | 该参数用于在使用limit做数据子集查询时,采样的最大文件数。 |
hive.limit.optimize.fetch.max | true | 50000 | 该参数用于当使用简单limit数据抽样时,允许的最大行数。 |
(2)参数文件配置:
启用桶Map连接优化参数配置示例:
<property>
<name>hive.limit.optimize.enable</name>
<value>true</value>
<description>Whether to enable to optimization to trying a smaller subset of data for simple LIMIT first.</description>
</property>
<property>
<name>hive.limit.row.max.size</name>
<value>100000</value>
<description>When trying a smaller subset of data for simple LIMIT, how much size we need to guarantee each row to have at least.
</description>
</property>
<property>
<name>hive.limit.optimize.limit.file</name>
<value>10</value>
<description>When trying a smaller subset of data for simple LIMIT, maximum number of files we can sample.
</description>
</property>
<property>
<name>hive.limit.optimize.fetch.max</name>
<value>50000</value>
<description>
Maximum number of rows allowed for a smaller subset of data for simple LIMIT, if it is a fetch query.
Insert queries are not restricted by this limit.
</description>
</property>
2.2.3启用MapReduce严格模式
Hive提供了一个严格模式,可以防止用户执行那些可能产生负面影响的查询。Hive提供了参数可进行约束,即启用MapReduce严格模式。
对此,笔者认为没有必要启用该参数,而应该养成良好地写sql语句的习惯。应当在每一次写sql语句时,时刻提醒自己防止灾难发生的可能。
此外,一旦该参数启用严格模式,会影响到其他参数的性能。因此不建议从配置文件配置该参数。
(1)参数优化说明:
参数 | 默认值 | 优化值 | 参数说明 |
hive.mapred.mode | 为空 | strict | 该参数用于是否启用MapReduce严格模式。 当使用limit语句时,对源数据进行抽样。 推荐该参数值配置成nonstrict。 该参数默认是关闭的。 |
(2)参数文件配置:
启用桶Map连接优化参数配置示例:
<property>
<name>hive.mapred.mode</name>
<value>strict</value>
<description>Deprecated; use hive.strict.checks.* settings instead.</description>
</property>
注:严格模式禁止3种类型的查询:
1)对于分区表,where子句中不包含分区字段过滤条件的查询语句不允许执行(很扯淡的限制)。
2)对于使用了order by子句的查询,要求必须使用limit子句(这是很鸡肋的做法),否则不允许执行。
3)限制笛卡尔积查询。(该种查询有时候是必须的,但应该尽量避免,绕道而行。)
2.3存储格式选择优化
Hive所支持的存储格式有:TextFile、SequenceFile、RCFile、Avro Files、ORC Files、Parquet。
(1)Hive所支持的存储格式说明
1)TextFile:
Hive默认格式,数据不做压缩,磁盘开销大,数据解析开销大。
可结合Gzip、Bzip2、Snappy等使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
2)SequenceFile:
SequenceFile是Hadoop API 提供的一种二进制文件,它将数据以<key,value>的形式序列化到文件中。
这种二进制文件内部使用Hadoop 的标准的Writable 接口实现序列化和反序列化。它与Hadoop API中的MapFile 是互相兼容的。
Hive 中的SequenceFile 继承自Hadoop API 的SequenceFile,不过它的key为空,使用value 存放实际的值, 这样是为了避免MR 在运行map 阶段的排序过程。
3)RCFile
RCFile是Hive推出的一种专门面向列的数据格式。 它遵循“先按列划分,再垂直划分”的设计理念。
当查询过程中,针对它并不关心的列时,它会在IO上跳过这些列。
需要说明的是,RCFile在map阶段从 远端拷贝仍然是拷贝整个数据块,并且拷贝到本地目录后RCFile并不是真正直接跳过不需要的列,并跳到需要读取的列,
而是通过扫描每一个row group的头部定义来实现的,但是在整个HDFS Block 级别的头部并没有定义每个列从哪个row group起始到哪个row group结束。
所以在读取所有列的情况下,RCFile的性能反而没有SequenceFile高。
4)ORC File
ORCFile代表了优化排柱状的文件格式。
ORC文件格式提供了一种将数据存储在Hive表中的高效方法。
这个文件系统实际上是为了克服其他Hive文件格式的限制而设计的。
Hive从大型表读取,写入和处理数据时,使用ORC文件可以提高性能。
5)Parquet
Parquet是一个面向列的二进制文件格式。
Parquet对于大型查询的类型是高效的。
对于扫描特定表格中的特定列的查询,Parquet特别有用。
Parquet使用压缩Snappy,gzip;目前Snappy默认。
6)Avro Files
AVRO是开源项目,为Hadoop提供数据序列化和数据交换服务。
可以在Hadoop生态系统和以任何编程语言编写的程序之间交换数据。
Avro是基于大数据Hadoop的应用程序中流行的文件格式之一。
(2)存储格式对比
1)对比1
存储格式 | 存储方式 | 特点 |
---|---|---|
TextFile | 行存储 | 存储空间消耗比较大,并且压缩的text 无法分割和合并。 查询的效率最低,可以直接存储,加载数据的速度最高。 |
SequenceFile | 行存储 | 存储空间消耗最大,压缩的文件可以分割和合并。 查询效率高,需要通过text文件转化来加载。 |
RCFile | 数据按行分块, 每块按照列存储 |
存储空间最小, 查询的效率最高 , 需要通过text文件转化来加载, 加载的速度最低。 压缩快 快速列存取。 读记录尽量涉及到的block最少 。 读取需要的列只需要读取每个row group 的头部定义。 读取全量数据的操作 性能可能比sequencefile没有明显的优势。 |
ORCFile | 数据按行分块, 每块按照列存储 |
压缩快,快速列存取 ,效率比rcfile高,是rcfile的改良版本。 |
Parquet | 列存储 | 相对于PRC,Parquet压缩比较低,查询效率较低, 不支持update、insert和ACID.但是Parquet支持Impala查询引擎。 |
2)对比2
如果仅仅是在HIve中存储和查询,建议使用ORC格式,如果在Hive中存储,而使用Impala查询,建议使用Parquet。
3)对比3
对比项 | Parquet:http://parquet.apache.org |
Orc:http://orc.apache.org |
发展状态 | 目前是Apache开源的顶级项目,列式存储引擎 | 目前是Apache开源的顶级项目,列式存储引擎 |
开发语言 | Java | Java |
主导公司 | Twitter/Cloudera | Hortonworks |
ACID |
不支持 | 支持ACID事务 |
修改操作 (update,delete) |
不支持 | 支持 |
支持索引 (统计信息) |
粗粒度索引 block/group/chunk级别统计信息 |
粗粒度索引 file/stripe/row级别统计信息, 不能精确到列建立索引 |
支持的查询引擎 | Apache Drill、Impala | Apache Hive |
查询性能 | Orc性能更高一点 | Orc性能更高一点 |
压缩比 | Orc压缩比更高 | Orc压缩比更高 |
列编码 | 支持多种编码,字典,RLE,Delta等 | 支持主流编码,与Parquet类似 |