hive调优参数.docx

上传人:b****6 文档编号:5362982 上传时间:2022-12-15 格式:DOCX 页数:16 大小:145.46KB
下载 相关 举报
hive调优参数.docx_第1页
第1页 / 共16页
hive调优参数.docx_第2页
第2页 / 共16页
hive调优参数.docx_第3页
第3页 / 共16页
hive调优参数.docx_第4页
第4页 / 共16页
hive调优参数.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

hive调优参数.docx

《hive调优参数.docx》由会员分享,可在线阅读,更多相关《hive调优参数.docx(16页珍藏版)》请在冰豆网上搜索。

hive调优参数.docx

hive调优参数

第一部分:

Hadoop计算框架的特性

什么是数据倾斜

由于数据的不均衡原因,导致数据分布不均匀,造成数据大量的集中到一点,造成数据热点。

Hadoop框架的特性

1)不怕数据大,怕数据倾斜

2)jobs数比较多的作业运行效率相对比较低,比如即使有几百行的表,如果多次关联多次汇总,产生十几个jobs,耗时很长。

原因是mapreduce作业初始化的时间是比较长的

3)sum,count,max,min等UDAF,不怕数据倾斜问题,hadoop在map端的汇总合并优化,使数据倾斜不成问题

4)count(distinct),在数据量大的情况下,效率较低,因为count(distinct)是按groupby字段分组,按distinct字段排序,一般这种分布方式是很倾斜的。

第二部分:

优化的常用手段

优化的常用手段

1)解决数据倾斜问题

2)减少job数

3)设置合理的mapreduce的task数,能有效提升性能。

4)了解数据分布,自己动手解决数据倾斜问题是个不错的选择

5)数据量较大的情况下,慎用count(distinct)。

6)对小文件进行合并,是行至有效的提高调度效率的方法。

7)优化时把握整体,单个作业最优不如整体最优。

第三部分:

Hive的数据类型方面的优化

优化原则

按照一定规则分区(例如根据日期)。

通过分区,查询的时候指定分区,会大大减少在无用数据上的扫描,同时也非常方便数据清理。

合理的设置Buckets。

在一些大数据join的情况下,mapjoin有时候会内存不够。

如果使用BucketMapJoin的话,可以只把其中的一个bucket放到内存中,内存中原来放不下的内存表就变得可以放下。

这需要使用buckets的键进行join的条件连结,并且需要如下设置

sethive.optimize.bucketmapjoin=true

第四部分:

Hive的操作方面的优化

全排序

Hive的排序关键字是SORTBY,它有意区别于传统数据库的ORDERBY也是为了强调两者的区别–SORTBY只能在单机范围内排序。

怎样做笛卡尔积

当Hive设定为严格模式(hive.mapred.mode=strict)时,不允许在HQL语句中出现笛卡尔积,MapJoin是的解决办法。

MapJoin,顾名思义,会在Map端完成Join操作。

这需要将Join操作的一个或多个表完全读入内存MapJoin的用法是在查询/子查询的SELECT关键字后面添加/*+MAPJOIN(tablelist)*/提示优化器转化为MapJoin(目前Hive的优化器不能自动优化MapJoin)其中tablelist可以是一个表,或以逗号连接的表的列表。

tablelist中的表将会读入内存,应该将小表写在这里在大表和小表做笛卡尔积时,规避笛卡尔积的方法是,给Join添加一个Joinkey,原理很简单:

将小表扩充一列joinkey,并将小表的条目复制数倍,joinkey各不相同;将大表扩充一列joinkey为随机数。

控制Hive的Map数

通常情况下,作业会通过input的目录产生一个或者多个map任务。

主要的决定因素有:

input的文件总个数,input的文件大小,集群设置的文件块大小(目前为128M,可在hive中通过setdfs.block.size;命令查看到,该参数不能自定义修改)。

是不是map数越多越好?

答案是否定的。

如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。

而且,同时可执行的map数是受限的是不是保证每个map处理接近128m的文件块,就高枕无忧了?

答案也是不一定。

比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。

针对上面的问题3和4,我们需要采取两种方式来解决:

即减少map数和增加map数;

是不是保证每个map处理接近128m的文件块,就高枕无忧了?

答案也是不一定。

比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。

针对上面的问题3和4,我们需要采取两种方式来解决:

即减少map数和增加map数;

举例:

a)假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和1个12m的块),从而产生7个map数。

b)假设input目录下有3个文件a,b,c,大小分别为10m,20m,130m,那么hadoop会分隔成4个块(10m,20m,128m,2m),从而产生4个map数。

即,如果文件大于块大小(128m),那么会拆分,如果小于块大小,则把该文件当成一个块。

怎样决定reducer个数

HadoopMapReduce程序中,reducer个数的设定极大影响执行效率,不指定reducer个数的情况下,Hive会猜测确定一个reducer个数,基于以下两个设定:

参数1:

hive.exec.reducers.bytes.per.reducer(默认为1G)

参数2:

hive.exec.reducers.max(默认为999)

计算reducer数的公式:

N=min(参数2,总输入数据量/参数1)

依据Hadoop的经验,可以将参数2设定为0.95*(集群中TaskTracker个数)reduce个数并不是越多越好。

同map一样,启动和初始化reduce也会消耗时间和资源;

另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题

什么情况下只有一个reduce很多时候你会发现任务中不管数据量多大,不管你有没有设置调整reduce个数的参数,任务中一直都只有一个reduce任务;

其实只有一个reduce任务的情况,除了数据量小于hive.exec.reducers.bytes.per.reducer参数值的情况外,还有以下原因:

a)没有groupby的汇总

b)用了Orderby

合并MapReduce操作

Multi-groupby是Hive的一个非常好的特性,它使得Hive中利用中间结果变得非常方便

FROMlog:

insertoverwritetabletest1selectlog.idgroupbylog.id

insertoverwritetabletest2selectlog.namegroupbylog.name

上述查询语句使用了Multi-groupby特性连续groupby了2次数据,使用不同的groupbykey。

这一特性可以减少一次MapReduce操作。

Bucket与Sampling

Bucket是指将数据以指定列的值为key进行hash,hash到指定数目的桶中。

这样就可以支持高效采样了Sampling可以在全体数据上进行采样,这样效率自然就低,它还是要去访问所有数据。

而如果一个表已经对某一列制作了bucket,就可以采样所有桶中指定序号的某个桶,这就减少了访问量。

如下例所示就是采样了test中32个桶中的第三个桶。

SELECT*FROMtest、、、TABLESAMPLE(BUCKET3OUTOF32);

JOIN原则

在使用写有Join操作的查询语句时有一条原则:

应该将条目少的表/子查询放在Join操作符的左边,原因是在Join操作的Reduce阶段,位于Join操作符左边的表的内容会被加载进内存,将条目少的表放在左边,可以有效减少发生OOM错误的几率。

MapJoin

Join操作在Map阶段完成,不再需要Reduce,前提条件是需要的数据在Map的过程中可以访问到

例如:

INSERTOVERWRITETABLEphone_traffic

SELECT/*+MAPJOIN(phone_location)*/l.phone,p.location,l.trafficfromphone_locationp

joinloglon(p.phone=l.phone);

相关的参数为:

hive.join.emit.interval=1000

Howmanyrowsintheright-mostjoinoperandHiveshouldbufferbeforeemittingthejoinresult.

hive.mapjoin.size.key=10000

hive.mapjoin.cache.numrows=10000

GroupBy

Map端部分聚合,并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在Reduce端得出最终结果基于Hash参数包括:

hive.map.aggr=true//是否在Map端进行聚合,默认为True

hive.groupby.mapaggr.checkinterval=100000//在Map端进行聚合操作的条目数目有数据倾斜的时候进行负载均衡

hive.groupby.skewindata=false

当选项设定为true,生成的查询计划会有两个MRJob。

第一个MRJob中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupByKey有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MRJob再根据预处理的数据结果按照GroupByKey分布到Reduce中(这个过程可以保证相同的GroupByKey被分布到同一个Reduce中),最后完成最终的聚合操作。

合并小文件

文件数目过多,会给HDFS带来压力,并且会影响处理效率,可以通过合并Map和Reduce的结果文件来消除这样的影响:

hive.merge.mapfiles=true//是否和并Map输出文件,默认为True

hive.merge.mapredfiles=false//是否合并Reduce输出文件,默认为False

hive.merge.size.per.task=256*1000*1000//合并文件的大小

排序优化

Order by 实现全局排序,一个reduce实现,效率低

Sort by 实现部分有序,单个reduce输出的结果是有序的,效率高,通常和DISTRIBUTE BY关键字一起使用(DISTRIBUTE BY关键字 可以指定map 到 reduce端的分发key)

CLUSTER BY col1 等价于DISTRIBUTE BY col1 SORT BY col1

使用分区

Hive中的每个分区都对应hdfs上的一个目录,分区列也不是表中的一个实际的字段,而是一个或者多个伪列,在表的数据文件中实际上并不保存分区列的信息与数据。

Partition关键字中排在前面的为主分区(只有一个),后面的为副分区

静态分区:

静态分区在加载数据和使用时都需要在sql语句中指定

   案例:

(stat_date='20120625',province='hunan')

动态分区:

使用动态分区需要设置hive.exec.dynamic.partition参数值为true,默认值为false,在默认情况下,hive会假设主分区时静态分区,副分区使用动态分区;如果想都使用动态分区,需要设置set hive.exec.dynamic.partition.mode=nostrick,默认为strick

          案例:

(stat_date='20120625',province)

Distinct 使用

Hive支持在group by时对同一列进行多次distinct操作,却不支持在同一个语句中对多个列进行distinct操作。

Hql使用自定义的mapred脚本

注意事项:

在使用自定义的mapred脚本时,关键字MAP REDUCE 是语句SELECT TRANSFORM ( ... )的语法转换,并不意味着使用MAP关键字时会强制产生一个新的map过程,使用REDUCE关键字时会产生一个red过程。

自定义的mapred脚本可以是hql语句完成更为复杂的功能,但是性能比hql语句差了一些,应该尽量避免使用,如有可能,使用UDTF函数来替换自定义的mapred脚本

回到顶部。

UDTF

UDTF将单一输入行转化为多个输出行,并且在使用UDTF时,select语句中不能包含其他的列,UDTF不支持嵌套,也不支持group by 、sort by等语句。

如果想避免上述限制,需要使用lateral view语法,案例:

select a.timestamp, get_a.appevents, '$.eventid'), get_a.appenvets, '$.eventname') from log a;

select a.timestamp, b.*

from log a lateral view a.appevent, 'eventid', 'eventname') b as f1, f2;

其中,get_json_object为UDF函数,json_tuple为UDTF函数。

UDTF函数在某些应用场景下可以大大提高hql语句的性能,如需要多次解析json或者xml数据的应用场景。

聚合函数count和sum

Count和sum函数可能是在hql语句中使用的最为频繁的两个聚合函数了,但是在hive中count函数在计算distinct value时支持加入条件过滤。

第五部分JVM重用、并行执行、调整reducer个数的用处

JVM重用

JVM重用是hadoop调优参数的内容,对hive的性能具有非常大的影响,特别是对于很难避免小文件的场景或者task特别多的场景,这类场景大多数执行时间都很短。

hadoop默认配置是使用派生JVM来执行map和reduce任务的,这是jvm的启动过程可能会造成相当大的开销,尤其是执行的job包含有成千上万个task任务的情况。

JVM重用可以使得JVM实例在同一个JOB中重新使用N次,N的值可以在Hadoop的mapre-site.xml文件中进行设置

mapred.job.reuse.jvm.num.tasks

也可在hive的执行设置:

setmapred.job.reuse.jvm.num.tasks=10;

JVM的一个缺点是,开启JVM重用将会一直占用使用到的task插槽,以便进行重用,直到任务完成后才能释放。

如果某个“不平衡“的job中有几个reducetask执行的时间要比其他reducetask消耗的时间多得多的话,那么保留的插槽就会一直空闲着却无法被其他的job使用,直到所有的task都结束了才会释放。

并行执行

并行执行,意思是同步执行hive的多个阶段,hive在执行过程,将一个查询转化成一个或者多个阶段。

某个特定的job可能包含众多的阶段,而这些阶段可能并非完全相互依赖的,也就是说可以并行执行的,这样可能使得整个job的执行时间缩短

hive执行开启:

sethive.exec.parallel=true

调整reducer个数

设置hive.exec.reducers.bytes.per.reducer(默认为1GB),受hive.exec.reducers.max(默认为999)影响:

mapred.reduce.tasks=min(参数2,总输入数据量/参数1)

三个优化的场景

采用一个数据源多份处理的SQL来执行:

FROMTABLE1

INSERTOVERWRITELOCALDIRECTORY'/data/data_table/data_table1.txt'SELECT20140303,col1,col2,2160701,COUNT(DISTINCTcol)WHEREcol3<=20140303ANDcol3>=20140201GROUPBYcol1,col2

INSERTOVERWRITELOCALDIRECTORY'/data/data_table/data_table2.txt'SELECT20140302,col1,col2,2160701,COUNT(DISTINCTcol)WHEREcol3<=20140302ANDcol3>=20140131GROUPBYcol1,col2

INSERTOVERWRITELOCALDIRECTORY'/data/data_table/data_table3.txt'SELECT20140301,col1,col2,2160701,COUNT(DISTINCTcol)WHEREcol3<=20140301ANDcol3>=20140130GROUPBYcol1,col2

INSERTOVERWRITELOCALDIRECTORY'/data/data_table/data_table4.txt'SELECT20140228,col1,col2,2160701,COUNT(DISTINCTcol)WHEREcol3<=20140228ANDcol3>=20140129GROUPBYcol1,col2

INSERTOVERWRITELOCALDIRECTORY'/data/data_table/data_table5.txt'SELECT20140227,col1,col2,2160701,COUNT(DISTINCTcol)WHEREcol3<=20140227ANDcol3>=20140128GROUPBYcol1,col2

INSERTOVERWRITELOCALDIRECTORY'/data/data_table/data_table6.txt'SELECT20140226,col1,col2,2160701,COUNT(DISTINCTcol)WHEREcol3<=20140226ANDcol3>=20140127GROUPBYcol1,col2

………………省略

没设置前的,执行时间是450s

设置参数:

setmapred.job.reuse.jvm.num.tasks=20

sethive.exec.reducers.bytes.per.reducer=150000000

sethive.exec.parallel=true;

执行时间缩短到273s,合理利用一个参数调整,可以达到部分调优

第六部分Hive的阶段进展

Hive的基础架构

基本组成

1)用户接口主要有三个:

CLI,Client和WUI。

其中最常用的是CLI,Cli启动的时候,会同时启动一个Hive副本。

Client是Hive的客户端,用户连接至HiveServer。

在启动Client模式的时候,需要指出HiveServer所在节点,并且在该节点启动HiveServer。

WUI是通过浏览器访问Hive。

2)Hive将元数据存储在数据库中,如mysql、derby。

Hive中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。

3)解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。

生成的查询计划存储在HDFS中,并在随后有MapReduce调用执行。

4)Hive的数据存储在HDFS中,大部分的查询、计算由MapReduce完成(包含*的查询,比如select*fromtbl不会生成MapRedcue任务)。

5)  Hive将元数据存储在RDBMS中

1.各组件的基本功能

1)用户接口主要有三个:

CLI,JDBC/ODBC和WebUI

2)CLI,即Shell命令行

3)JDBC/ODBC是Hive的JAVA,与使用传统数据库JDBC的方式类似

4)WebGUI是通过浏览器访问Hive

5)Hive将元数据存储在数据库中,目前只支持mysql、derby,下一版本会支持更多的数据库。

Hive中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等

6)解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。

生成的查询计划存储在HDFS中,并在随后有MapReduce调用执行

7)Hive的数据存储在HDFS中,大部分的查询由MapReduce完成(包含*的查询,比如select*fromtable不会生成MapRedcue任务)。

2.Metastore

1)Metastore是系统目录(catalog)用于保存Hive中所存储的表的元数据(metadata)信息

2)Metastore是Hive被用作传统数据库解决方案(如oracle和db2)时区别其它类似系统的一个特征

3)Metastore包含如下的部分:

Database是表(table)的名字空间。

默认的数据库(database)名为‘default’。

Table表(table)的原数据包含信息有:

列(listofcolumns)和它们的类型(types),拥有者(owner),存储空间(storage)和SerDei信息。

Partition每个分区(partition)都有自己的列(columns),SerDe和存储空间(storage)。

这一特征将被用来支持Hive中的模式演变(schemaevolution)。

3.Compiler

1)Driver调用编译器(compiler)处理HiveQL字串,这些字串可能是一条DDL、DML或查询语句

2)编译器将字符串转化为策略(plan)

3)策略仅由元数据操作和HDFS操作组成,元数据操作只包含DDL语句,HDFS操作只包含LOAD语句

4)对插入和查询而言,策略由map-reduce任务中的具有方向的非循环图(directedacyclicgraph,DAG)组成

Hive的数据元数据

(表相关信息)存在关系数据库中。

为什么要存在RDBMS中,获取元数据信息需要很低的延时,这在hdfs上是无法满足。

分析HiveSQL之后生成的MapReduce任务在运行的时候如果需要访问

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 其它

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1