Hive文件存储格式查询性能的比较

一、Hive的文件存储格式

Hive总共支持以下几种文件存储格式:

  • Text File
  • SequenceFile
  • RCFile
  • Avro Files
  • ORC Files
  • Parquet
  • Custom INPUTFORMAT and OUTPUTFORMAT

    这里,我们主要比较Text File,ORC File,Parquet文件存储格式的查询性能,在比较之前,我们先简单介绍一下这三种文件存储格式。对于Text File就是我们默认的存储格式,行式存储,这里就不用讲解了。
    ORC File

1.ORC介绍

什么是ORC文件存储格式呢?先看看官网的介绍:

The Optimized Row Columnar (ORC) file format provides a highly efficient way to store Hive data. It was designed to overcome limitations of the other Hive file formats. Using ORC files improves performance when Hive is reading, writing, and processing data.

ORC全称(Optimized Row Columnar),是一种高效的存储数据的文件格式,克服了其他文件格式的一些限制,提高了Hive读写数据的性能。

ORC实际上是在RC文件存储格式做了一些优化,它的主要优点有:
  (1)、每个task只输出单个文件,这样可以减少NameNode的负载;
  (2)、支持各种复杂的数据类型,比如: datetime, decimal, 以及一些复杂类型(struct, list, map, and union);
  (3)、在文件中存储了一些轻量级的索引数据;
  (4)、基于数据类型的块模式压缩:a、integer类型的列用行程长度编码(run-length encoding);b、String类型的列用字典编码(dictionary encoding);
  (5)、用多个互相独立的RecordReaders并行读相同的文件;
  (6)、无需扫描markers就可以分割文件;
  (7)、绑定读写所需要的内存;
  (8)、metadata的存储是用 Protocol Buffers的,所以它支持添加和删除一些列。

2.ORC结构

下图是官网的ORC结构图:
这里写图片描述

在ORC格式存储的表中,它会将记录横向切分为多个stripes,每一个stripe以列为单位进行存储,所有列会保存在一个文件中,每个stripe的默认大小为256MB,相对于RCFile每个4MB的stripe而言,更大的stripe使ORC的数据读取更加高效。
关于更详细的介绍可查看官网【https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC
hortonwork公司的介绍【https://zh.hortonworks.com/blog/orcfile-in-hdp-2-better-compression-better-performance/

PARQUET格式

Parquet仅仅是一种存储格式,它是语言、平台无关的,并且不需要和任何一种数据处理框架绑定,目前能够和Parquet适配的组件包括下面这些,可以看出基本上通常使用的查询引擎和计算框架都已适配,并且可以很方便的将其它序列化工具生成的数据转换成Parquet格式。

  • 查询引擎: Hive, Impala, Pig, Presto, Drill, Tajo, HAWQ, IBM Big SQL
  • 计算框架: MapReduce, Spark, Cascading, Crunch, Scalding, Kite
  • 数据模型: Avro, Thrift, Protocol Buffers, POJOs

二、性能比较

在进行测试之前,我们先看看HortonWork公司官网对这几种存储格式的比较分析:
这里写图片描述
从图中很明显看到ORC存储格式和Parquet存储格式对文件的存储比Text格式小很多,也就是说压缩比大很多。下面我们来实践测试一下。
为了进行比较测试三种存储格式,首先创建三张表,并且每一张表中插入100000表数据:

create table page_view(
user_ip string,
username string,
user_time string,
request_url string,
request_state string,
request_port string,
limited string,
des_url string,
brower string,
brower_limit string,
to_url string
)
row format delimited fields terminated by '\t'
stored as TEXTFILE;

load data local inpath '/opt/datas/page_view.log' into table page_view;

create table page_view_orc(
user_ip string,
username string,
user_time string,
request_url string,
request_state string,
request_port string,
limited string,
des_url string,
brower string,
brower_limit string,
to_url string
)
row format delimited fields terminated by '\t'
stored as ORC;

insert into table page_view_orc select * from page_view;

create table page_view_parquet(
user_ip string,
username string,
user_time string,
request_url string,
request_state string,
request_port string,
limited string,
des_url string,
brower string,
brower_limit string,
to_url string
)
row format delimited fields terminated by '\t'
stored as PARQUET;

insert into table page_view_parquet select * from page_view;

在创建好表之后,先来看看100000条数据在不同文件存储格式的存储下的大小:

#查看这三种格式的文件的大小:
dfs -du -h /user/hive/warehouse/db_hive.db/page_view;
34.0 M  /user/hive/warehouse/db_hive.db/page_view/page_view.log

dfs -du -h /user/hive/warehouse/db_hive.db/page_view_orc;
125.4 K  /user/hive/warehouse/db_hive.db/page_view_orc/000000_0

dfs -du -h /user/hive/warehouse/db_hive.db/page_view_parquet;
34.3 M  /user/hive/warehouse/db_hive.db/page_view_parquet/000000_0

很明显,在ORC格式存储的文件中,大小比Text小很多,也印证了上图。至于Parquet为什么和Text格式相差不多,可能是因为数据量不够大,但是通常情况下parquet存储相同的数据占用的大小会比TEXT格式要小。

接着,我们来编写查询语句,比较它们的查询速度:

#测试三种存储格式查询数据的速度
select user_time,count(*) cnt from page_view group by user_time order by cnt desc limit 20;
Time taken: 73.15 seconds, Fetched: 1 row(s)

select user_time,count(*) cnt from page_view_orc group by user_time order by cnt desc limit 20;
Time taken: 57.091 seconds, Fetched: 1 row(s)

select user_time,count(*) cnt from page_view_parquet group by user_time order by cnt desc limit 20;
Time taken: 55.526 seconds, Fetched: 1 row(s)

select count(*) from page_view;
Time taken: 25.124 seconds, Fetched: 1 row(s)

select count(*) from page_view_orc;
Time taken: 25.759 seconds, Fetched: 1 row(s)

select count(*) from page_view_parquet;
Time taken: 24.998 seconds, Fetched: 1 row(s)

从上面的查询耗时的结果上看,在执行比较复杂的查询语句时,ORC格式和Parquet格式要比Text格式快很多。

从上面的结果可以得出结论:ORC和Parquet存储格式要比Text格式读写数据的性能要好,在企业中一般大多情况下回采用这两种存储格式。
这时,我们可能要问为什么这两种存储格式的性能会好?什么时候用到这两种存储格式呢?这里简单说明一下,在很多时候,我们查询语句都会用到where语句对某一列进行筛选,如果采用行式存储格式(TEXT File),我们要在一行中找出对应的列,然后再进行筛选,而使用ORC和Parquet列式存储格式,会直接定位在某一列进行筛选,因此性能会提高很多。

最后,我们来讲一下ORC支持的压缩格式,ORC支持三种压缩:Lzip,Snappy,none。最后一种就是不压缩。

这里我们也可以实际测试一下lzip和snappy的压缩比:

#测试压缩:

create table page_view_orc_snappy(
user_ip string,
username string,
user_time string,
request_url string,
request_state string,
request_port string,
limited string,
des_url string,
brower string,
brower_limit string,
to_url string
)
row format delimited fields terminated by '\t'
stored as ORC tblproperties ("orc.compress"="SNAPPY");  #snappy大写

insert into table page_view_orc_snappy select * from page_view;     #会执行三个mapreduce程序,select,转换为orc格式,snappy压缩
Time taken: 17.879 seconds

select count(*) from page_view_orc_snappy;
Time taken: 26.956 seconds, Fetched: 1 row(s)

dfs -du -h /user/hive/warehouse/db_hive.db/page_view_orc_snappy;
329.4 K  /user/hive/warehouse/db_hive.db/page_view_orc_snappy/000000_0
#因为orc默认的是lzip,压缩比大于snappy

这里我们在采用snappy压缩格式来创建一张表后,相同的数据大小为329.4k,而在上面我们可以看到ORC格式采用默认的压缩格式大小为125.4 K,为什么压缩后反而会变大呢?有很多人敢打很奇怪,实际上ORC默认的压缩格式是lzip格式,这也说明lizp的压缩比大于snappy的压缩比。

综上,我们可以得出,在处理较大数据,进行复杂的查询时可以采用ORC或者Parquet存储格式以及压缩的方式来处理数据会提高很多性能。

猜你喜欢

转载自blog.csdn.net/qq_37142346/article/details/79873376