Hive 计算引擎性能测试

1、运行模式(本地模式/集群模式)

1.job的输入数据大小必须小于参数:hive.exec.mode.local.auto.inputbytes.max(默认128MB)

2.job的map数必须小于参数:hive.exec.mode.local.auto.tasks.max(默认4)。而Map task个数是有default_num = total_size / block_size计算得出;

3.job的reduce数必须为0或者1

可用参数hive.mapred.local.mem(默认0)控制child jvm使用的最大内存数。

本地模式下需要注意设置 mapred.local.dir 本地目录,并且赋予执行用户权限。不然会出现No space available in any of the local directories 异常。

使用场景:

有时Hive的输入数据量是非常小的。在这种情况下,为查询触发执行任务消耗的时间可能会比实际job的执行时间要多的多。对于大多数这种情况,Hive可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间可以明显被缩短。

用户可以通过设置hive.exec.mode.local.auto的值为true,来让Hive在适当的时候自动启动这个优化。

 

这边对如下数据做测试,总的数据大小为161B:

查询语句:select salary,count(*) from employee group by salary;

集群模式下:

本地模式下:

从上面执行的结果可以看出,执行时间明显的缩短。

2、计算引擎 (MR/TEZ/SPARK)

hive默认引擎是mr,执行job时可以看到上面日志,HIVE2后已经建议使用tez/spark计算引擎。

hive 的引擎设置   hive.execution.engine

下列对 数据量为 14401261 条,大小为2.8G的 textfile格式的数据进行测试。

测试执行语句:

select cs_sold_date_sk,count(*) from catalog_sales group by cs_sold_date_sk;

MR:

set hive.execution.engine=mr;

测试的平均值在38秒左右

TEZ:

set hive.execution.engine=tez;

对比MR,TEZ的优化技术:

产生一个Mapreduce任务就提交,影响任务的效率,Tez的优化策略是创建一个ApplicationMaster的缓存池,作业提交到AMppplserver中,预先启动若干ApplicationMaster形成AM缓冲池。

同时ApplicationMaster启动的时候也可以预先启动几个container,做为容器的缓冲池。

此外ApplicationMaster运行完成后,不会马上注销其下的container,而是将其预先分配给正要运行的任务。

Tez的好处就是避免产生较多的Mapreduce任务,产生不必要的网络和磁盘IO.

下图是运行完后保留的ApplicationMaster。

测试分三种情况如果执行完上一次,立即再次执行平均只需要7秒左右。如果等container资源释放后再执行则平均需要13秒,等applicationMaster结束再执行的话需要17秒。

SPARK:

set hive.execution.engine=spark;

除了第一次连接过程需要较长的时间20s,后续的执行平均只需要6秒完成。

以下是spark的运行情况

hive 使用 spark引擎 部署配置遇到问题可以查看 Hive on Spark

3、文件存储格式

Hive中常用文件存储格式有

  • TextFile 行存储  默认格式,数据不做压缩,磁盘开销大,数据解析开销大。可结合Gzip、Bzip2使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
  • Parquet 列存储  最初的设计动机是存储嵌套式数据,比如Protocolbuffer,thrift,json等,将这类数据存储成列式格式,以方便对其高效压缩和编码,且使用更少的IO操作取出需要的数据,这也是Parquet相比于ORC的优势,它能够透明地将Protobuf和thrift类型的数据进行列式存储。不支持update操作(数据写成后不可修改)。
  • ORC 列式存储  默认zlib压缩  ORC是在一定程度上扩展了RCFile,是对RCFile的优化。ORC是列式存储,有多种文件压缩方式,并且有着很高的压缩比。文件是可切分(Split)的。因此,在Hive中使用ORC作为表的文件存储格式,不仅节省HDFS存储资源,查询任务的输入数据量减少,使用的MapTask也就减少了。提供了多种索引,row group index、bloom filter index。ORC可以支持复杂的数据结构(比如Map等)
  • Sequence 行存储  二进制文件,以<key,value>的形式序列化到文件中,SequenceFile是Hadoop API提供的一种二进制文件支持,其具有使用方便、可分割、可压缩的特点。SequenceFile支持三种压缩选择:NONE,RECORD,BLOCK。Record压缩率低,一般建议使用BLOCK压缩。
  • RC  RCFile 列存储 文件格式是FaceBook开源的一种Hive的文件存储格式,首先将表分为几个行组,对每个行组内的数据进行按列存储,每一列的数据都是分开存储,正是先水平划分,再垂直划分的理念。
  • AVRO 行式存储  一种远程过程调用和数据序列化框架,是在Apache的Hadoop项目之内开发的。它使用JSON来定义数据类型和通讯协议,可以在Hadoop生态系统和以任何编程语言编写的程序之间交换数据,使用压缩二进制格式来序列化数据。

下面对以上存储格式进行存储空间和SQL查询两个方面的比较.

采用MR计算引擎,执行三次以上平局值。以14401261 条,大小为2.8G的 textfile格式的数据作为源表。

文件存储格式HDFS存储空间

不含group by

select count(*) from table

含group by

select cs_sold_date_sk,count(*) from table group by cs_sold_date_sk limit 1;

TextFile2.8G46s84s
Parquet1.2G22s36s
ORC711.8 M12s19.3s
Sequence3.0 G182s222s
RC1.8 G40s66s
AVRO1.8G265s290s

从上面的测试结果可以看出

  • 从占用存储空间来看,ORC和Parquet文件格式占用的空间相对而言要小得多。
  • 从执行SQL效率来看,ORC和Parquet文件格式查询耗时要相对而言要小得多。

 

从目前所得的结论来看,Hive中选用ORC和Parquet文件格式似乎更好一点,但是Hive默认的文件存储格式是TextFile,这是因为大多数情况下源数据文件都是以text文件格式保存(便于查看验数和防止乱码),这样TextFile文件格式的Hive表能直接load data数据。
如果说我们想使用ORC文件或者Parquet文件格式的表数据,可以先通过TextFile表加载后再insert到指定文件存储格式的表中。而这些不同文件格式的表我们可以通过数据分层保存,便于后期进行数据统计。

对于ORC和Parquet的选择,从上面的结论ORC比Parquet要好。但是由于ORC的一些局限性,比如Impala不支持orc,实际生产中使用Parquet比较多。

Hive数仓建表该选用ORC还是Parquet,压缩选LZO还是Snappy?

 

TextFile

select count(*) from catalog_sales;

select cs_sold_date_sk,count(*) from catalog_sales group by cs_sold_date_sk limit 1;

Parquet

CREATE EXTERNAL TABLE `catalog_sales_parquet`( `cs_sold_date_sk` bigint, `cs_sold_time_sk` bigint, `cs_ship_date_sk` bigint, `cs_bill_customer_sk` bigint, `cs_bill_cdemo_sk` bigint, `cs_bill_hdemo_sk` bigint, `cs_bill_addr_sk` bigint, `cs_ship_customer_sk` bigint, `cs_ship_cdemo_sk` bigint, `cs_ship_hdemo_sk` bigint, `cs_ship_addr_sk` bigint, `cs_call_center_sk` bigint, `cs_catalog_page_sk` bigint, `cs_ship_mode_sk` bigint, `cs_warehouse_sk` bigint, `cs_item_sk` bigint, `cs_promo_sk` bigint, `cs_order_number` bigint, `cs_quantity` int, `cs_wholesale_cost` decimal(7,2), `cs_list_price` decimal(7,2), `cs_sales_price` decimal(7,2), `cs_ext_discount_amt` decimal(7,2), `cs_ext_sales_price` decimal(7,2), `cs_ext_wholesale_cost` decimal(7,2), `cs_ext_list_price` decimal(7,2), `cs_ext_tax` decimal(7,2), `cs_coupon_amt` decimal(7,2), `cs_ext_ship_cost` decimal(7,2), `cs_net_paid` decimal(7,2), `cs_net_paid_inc_tax` decimal(7,2), `cs_net_paid_inc_ship` decimal(7,2), `cs_net_paid_inc_ship_tax` decimal(7,2), `cs_net_profit` decimal(7,2)) ROW format delimited fields terminated by '|' stored as parquet;

insert overwrite table catalog_sales_parquet select * from catalog_sales;

select count(*) from catalog_sales_parquet;

select cs_sold_date_sk,count(*) from catalog_sales_parquet group by cs_sold_date_sk limit 1;

ORC 

CREATE EXTERNAL TABLE `catalog_sales_orc`( `cs_sold_date_sk` bigint, `cs_sold_time_sk` bigint, `cs_ship_date_sk` bigint, `cs_bill_customer_sk` bigint, `cs_bill_cdemo_sk` bigint, `cs_bill_hdemo_sk` bigint, `cs_bill_addr_sk` bigint, `cs_ship_customer_sk` bigint, `cs_ship_cdemo_sk` bigint, `cs_ship_hdemo_sk` bigint, `cs_ship_addr_sk` bigint, `cs_call_center_sk` bigint, `cs_catalog_page_sk` bigint, `cs_ship_mode_sk` bigint, `cs_warehouse_sk` bigint, `cs_item_sk` bigint, `cs_promo_sk` bigint, `cs_order_number` bigint, `cs_quantity` int, `cs_wholesale_cost` decimal(7,2), `cs_list_price` decimal(7,2), `cs_sales_price` decimal(7,2), `cs_ext_discount_amt` decimal(7,2), `cs_ext_sales_price` decimal(7,2), `cs_ext_wholesale_cost` decimal(7,2), `cs_ext_list_price` decimal(7,2), `cs_ext_tax` decimal(7,2), `cs_coupon_amt` decimal(7,2), `cs_ext_ship_cost` decimal(7,2), `cs_net_paid` decimal(7,2), `cs_net_paid_inc_tax` decimal(7,2), `cs_net_paid_inc_ship` decimal(7,2), `cs_net_paid_inc_ship_tax` decimal(7,2), `cs_net_profit` decimal(7,2)) ROW format delimited fields terminated by '|' stored as orc;

insert overwrite table catalog_sales_orc select * from catalog_sales;

select count(*) from catalog_sales_orc;

select cs_sold_date_sk,count(*) from catalog_sales_orc group by cs_sold_date_sk limit 1;

SequenceFile

CREATE EXTERNAL TABLE `catalog_sales_sequence`( `cs_sold_date_sk` bigint, `cs_sold_time_sk` bigint, `cs_ship_date_sk` bigint, `cs_bill_customer_sk` bigint, `cs_bill_cdemo_sk` bigint, `cs_bill_hdemo_sk` bigint, `cs_bill_addr_sk` bigint, `cs_ship_customer_sk` bigint, `cs_ship_cdemo_sk` bigint, `cs_ship_hdemo_sk` bigint, `cs_ship_addr_sk` bigint, `cs_call_center_sk` bigint, `cs_catalog_page_sk` bigint, `cs_ship_mode_sk` bigint, `cs_warehouse_sk` bigint, `cs_item_sk` bigint, `cs_promo_sk` bigint, `cs_order_number` bigint, `cs_quantity` int, `cs_wholesale_cost` decimal(7,2), `cs_list_price` decimal(7,2), `cs_sales_price` decimal(7,2), `cs_ext_discount_amt` decimal(7,2), `cs_ext_sales_price` decimal(7,2), `cs_ext_wholesale_cost` decimal(7,2), `cs_ext_list_price` decimal(7,2), `cs_ext_tax` decimal(7,2), `cs_coupon_amt` decimal(7,2), `cs_ext_ship_cost` decimal(7,2), `cs_net_paid` decimal(7,2), `cs_net_paid_inc_tax` decimal(7,2), `cs_net_paid_inc_ship` decimal(7,2), `cs_net_paid_inc_ship_tax` decimal(7,2), `cs_net_profit` decimal(7,2)) ROW format delimited fields terminated by '|' stored as sequencefile;

insert overwrite table catalog_sales_sequence select * from catalog_sales;

select count(*) from catalog_sales_sequence;

select cs_sold_date_sk,count(*) from catalog_sales_sequence group by cs_sold_date_sk limit 1;

RCFile

CREATE EXTERNAL TABLE `catalog_sales_rc`( `cs_sold_date_sk` bigint, `cs_sold_time_sk` bigint, `cs_ship_date_sk` bigint, `cs_bill_customer_sk` bigint, `cs_bill_cdemo_sk` bigint, `cs_bill_hdemo_sk` bigint, `cs_bill_addr_sk` bigint, `cs_ship_customer_sk` bigint, `cs_ship_cdemo_sk` bigint, `cs_ship_hdemo_sk` bigint, `cs_ship_addr_sk` bigint, `cs_call_center_sk` bigint, `cs_catalog_page_sk` bigint, `cs_ship_mode_sk` bigint, `cs_warehouse_sk` bigint, `cs_item_sk` bigint, `cs_promo_sk` bigint, `cs_order_number` bigint, `cs_quantity` int, `cs_wholesale_cost` decimal(7,2), `cs_list_price` decimal(7,2), `cs_sales_price` decimal(7,2), `cs_ext_discount_amt` decimal(7,2), `cs_ext_sales_price` decimal(7,2), `cs_ext_wholesale_cost` decimal(7,2), `cs_ext_list_price` decimal(7,2), `cs_ext_tax` decimal(7,2), `cs_coupon_amt` decimal(7,2), `cs_ext_ship_cost` decimal(7,2), `cs_net_paid` decimal(7,2), `cs_net_paid_inc_tax` decimal(7,2), `cs_net_paid_inc_ship` decimal(7,2), `cs_net_paid_inc_ship_tax` decimal(7,2), `cs_net_profit` decimal(7,2)) ROW format delimited fields terminated by '|' stored as rcfile;

insert overwrite table catalog_sales_rc select * from catalog_sales;

select count(*) from catalog_sales_rc;

select cs_sold_date_sk,count(*) from catalog_sales_rc group by cs_sold_date_sk limit 1;

AVRO

CREATE EXTERNAL TABLE `catalog_sales_avro`( `cs_sold_date_sk` bigint, `cs_sold_time_sk` bigint, `cs_ship_date_sk` bigint, `cs_bill_customer_sk` bigint, `cs_bill_cdemo_sk` bigint, `cs_bill_hdemo_sk` bigint, `cs_bill_addr_sk` bigint, `cs_ship_customer_sk` bigint, `cs_ship_cdemo_sk` bigint, `cs_ship_hdemo_sk` bigint, `cs_ship_addr_sk` bigint, `cs_call_center_sk` bigint, `cs_catalog_page_sk` bigint, `cs_ship_mode_sk` bigint, `cs_warehouse_sk` bigint, `cs_item_sk` bigint, `cs_promo_sk` bigint, `cs_order_number` bigint, `cs_quantity` int, `cs_wholesale_cost` decimal(7,2), `cs_list_price` decimal(7,2), `cs_sales_price` decimal(7,2), `cs_ext_discount_amt` decimal(7,2), `cs_ext_sales_price` decimal(7,2), `cs_ext_wholesale_cost` decimal(7,2), `cs_ext_list_price` decimal(7,2), `cs_ext_tax` decimal(7,2), `cs_coupon_amt` decimal(7,2), `cs_ext_ship_cost` decimal(7,2), `cs_net_paid` decimal(7,2), `cs_net_paid_inc_tax` decimal(7,2), `cs_net_paid_inc_ship` decimal(7,2), `cs_net_paid_inc_ship_tax` decimal(7,2), `cs_net_profit` decimal(7,2)) ROW format delimited fields terminated by '|' stored as avro;

insert overwrite table catalog_sales_avro select * from catalog_sales;

select count(*) from catalog_sales_avro;

select cs_sold_date_sk,count(*) from catalog_sales_avro group by cs_sold_date_sk limit 1;

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值