Hive调优及参数优化(详细版)

您所在的位置:网站首页 vivoyx20参数配置参 Hive调优及参数优化(详细版)

Hive调优及参数优化(详细版)

2023-10-12 21:46| 来源: 网络整理| 查看: 265

1 Hive参数优化 1.1 Hive基础配置 1.1.1 HiveServer2 的 Java 堆栈

Hiveserver2异常退出,导致连接失败的问题。 解决方法:修改HiveServer2 的 Java 堆栈大小。

1.1.2 SQL中limit用的较多时

limit 语句快速出结果一般情况下,Limit语句还是需要执行整个查询语句,然后再返回部分结果。有一个配置属性可以开启,避免这种情况。

Set hive.limit.optimize.enable=true;--(默认为false) Set hive.limit.row.max.size=100000;--(limit最多可以查询多少行,根据需求可以调大) Set hive.limit.optimize.limit.file=10;--(一个查询可以操作的最多文件数,根据需要适当调大) Set hive.limit.optimize.fetch.max=50000;--(fetch query,直接select from,能够获取的最大行数) 1.1.3 Hive执行引擎

        CDH支持的引擎包括MapReduce和Spark两种,可自由选择,Spark不一定比MR快,Hive2.x和Hadoop3.x经过多次优化,Hive-MR引擎的性能已经大幅提升。

1.2 压缩配置 1.2.1 Map输出压缩

        除了创建表时指定保存数据时压缩,在查询分析过程中,Map的输出也可以进行压缩。由于map任务的输出需要写到磁盘并通过网络传输到reducer节点,所以通过使用LZO、LZ4或者Snappy这样的快速压缩方式,是可以获得性能提升的,因为需要传输的数据减少了。

MapReduce配置项: --设置是否启动map输出的压缩机制,默认为false。在需要减少网络传输的时候,可以设置为true。 set mapreduce.map.output.compress 1.2.2 Reduce结果压缩

        是否对任务输出产生的结果进行压缩,默认值false。对传输数据进行压缩,既可以减少文件的存储空间,又可以加快数据在网络不同节点之间的传输速度。

1.2.3 Hive的Map-Reduce之间是否进行压缩

        控制 Hive 在多个 map-reduce 作业之间生成的中间 files 是否被压缩。压缩编解码器和其他选项由上面Job的变量mapreduce.output.fileoutputformat.compress.*确定。

set hive.exec.compress.intermediate=true; 1.2.4 Hive查询最终结果压缩

        控制是否压缩查询的最终输出(到 local/hdfs 文件或 Hive table)。压缩编解码器和其他选项由 上面Job中的变量mapreduce.output.fileoutputformat.compress.*确定。

set hive.exec.compress.output=true; 2 Hive优化 2.1 Hive分桶

        分桶是将数据集分解成更容易管理的若干部分的一个技术,是比分区更为细粒度的数据范围划分。

2.1.1 为什么要分桶

2.1.1.1 获得更高的查询处理效率

        在分区数量过于庞大以至于可能导致文件系统崩溃时,或数据集找不到合理的分区字段时,我们就需要使用分桶来解决问题了。         分区中的数据可以被进一步拆分成桶,不同于分区对列直接进行拆分,桶往往使用列的哈希值对数据打散,并分发到各个不同的桶中从而完成数据的分桶过程。         注意,hive使用对分桶所用的值进行hash,并用hash结果除以桶的个数做取余运算的方式来分桶,保证了每个桶中都有数据,但每个桶中的数据条数不一定相等。         如果另外一个表也按照同样的规则分成了一个个小文件。两个表join的时候,就不必要扫描整个表,只需要匹配相同分桶的数据即可,从而提升效率。         在数据量足够大的情况下,分桶比分区有更高的查询效率。

2.1.1.2 数据采样

        在真实的大数据分析过程中,由于数据量较大,开发和自测的过程比较慢,严重影响系统的开发进度。此时就可以使用分桶来进行数据采样。采样使用的是一个具有代表性的查询结果而不是全部结果,通过对采样数据的分析,来达到快速开发和自测的目的,节省大量的研发成本。        

2.1.2 分桶与分区的区别 分桶和分区两者不干扰,可以把分区表进一步分桶;分桶对数据的处理比分区更加细粒度化:分区针对的是数据的存储路径;分桶针对的是数据文件;分桶是按照列的哈希函数进行分割的,相对比较平均;而分区是按照列的值来进行分割的,容易造成数据倾斜。 2.1.3 文本数据处理

        注意:对于分桶表,不能使用load data的方式进行数据插入操作,因为load data导入的数据不会有分桶结构。

如何避免针对桶表使用load data插入数据的误操作呢? --限制对桶表进行load操作 set hive.strict.checks.bucketing = true;

        也可以在CM的hive配置项中修改此配置,当针对桶表执行load data操作时会报错。

那么对于文本数据如何处理呢? 1. 先创建临时表,通过load data将txt文本导入临时表。 --创建临时表 create table temp_buck(id int, name string) row format delimited fields terminated by '\t'; --导入数据 load data local inpath '/tools/test_buck.txt' into table temp_buck; 2. 使用insert select语句间接的把数据从临时表导入到分桶表。 --启用桶表 set hive.enforce.bucketing=true; --限制对桶表进行load操作 set hive.strict.checks.bucketing = true; --insert select insert into table test_buck select id, name from temp_buck; --分桶成功 2.1.4 Map join

        MapJoin顾名思义,就是在Map阶段进行表之间的连接。而不需要进入到Reduce阶段才进行连接。这样就节省了在Shuffle阶段时要进行的大量数据传输。从而起到了优化作业的作用。         要使MapJoin能够顺利进行,那就必须满足这样的条件:除了一份表的数据分布在不同的Map中外,其他连接的表的数据必须在每个Map中有完整的拷贝。         所以并不是所有的场景都适合用MapJoin。它通常会用在如下的一些情景:在二个要连接的表中,有一个很大,有一个很小,这个小表可以存放在内存中而不影响性能。         这样我们就把小表文件复制到每一个Map任务的本地,再让Map把文件读到内存中待用。         在Hive v0.7之前,需要使用hint提示 /*+ mapjoin(table) */才会执行MapJoin。Hive v0.7之后的版本已经不需要给出MapJoin的指示就进行优化。现在可以通过如下配置参数来进行控制:    

set hive.auto.convert.join=true;     Hive还提供另外一个参数--表文件的大小作为开启和关闭MapJoin的阈值: --旧版本为hive.mapjoin.smalltable.filesize set hive.auto.convert.join.noconditionaltask.size=512000000

注意:如果hive.auto.convert.join是关闭的,则本参数不起作用。否则,如果参与连接的N个表(或分区)中的N-1个 的总大小小于512MB,则直接将连接转为Map连接。默认值为20MB。 

MapJoin的使用场景:

关联操作中有一张表非常小不等值的链接操作

2.1.4.1 大小表关联

select f.a,f.b from A t join B f on ( f.a=t.a and f.ftime=20110802)

        该语句中B表有30亿行记录,A表只有100行记录,而且B表中数据倾斜特别严重,有一个key上有15亿行记录,在运行过程中特别的慢,而且在reduece的过程中遇到执行时间过长或者内存不够的问题。         MAPJION会把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map时进行了join操作,省去了reduce运行的效率会高很多。         这样就不会由于数据倾斜导致某个reduce上落数据太多而失败。于是原来的sql可以通过使用hint的方式指定join时使用mapjoin。

select /*+ mapjoin(A)*/ f.a,f.b from A t join B f on ( f.a=t.a and f.ftime=20110802)

        在实际使用中,只要根据业务调整小表的阈值即可,hive会自动帮我们完成mapjoin,提高执行的效率。

2.1.4.2 不等连接

        mapjoin还有一个很大的好处是能够进行不等连接的join操作,如果将不等条件写在where中,那么mapreduce过程中会进行笛卡尔积,运行效率特别低,如果使用mapjoin操作,在map的过程中就完成了不等值的join操作,效率会高很多。

select A.a ,A.b from A join B where A.a>B.a

2.1.4.3 使用限制

LEFT OUTER JOIN的左表必须是大表;RIGHT OUTER JOIN的右表必须是大表;INNER JOIN左表或右表均可以作为大表;FULL OUTER JOIN不能使用MAPJOIN;MAPJOIN支持小表为子查询;使用MAPJOIN时需要引用小表或是子查询时,需要引用别名;在MAPJOIN中,可以使用不等值连接或者使用OR连接多个条件;在MAPJOIN中最多支持指定6张小表,否则报语法错误;如果使用MAPJOIN,则所有小表占用的内存总和不得超过设置的内存(解压后的逻辑数据量)。 2.1.5 Bucket-Map Join

2.1.5.1 作用

        两个表join的时候,小表不足以放到内存中,但是又想用map side join这个时候就要用到bucket Map join。其方法是两个join表在join key上都做hash bucket,并且把你打算复制的那个(相对)小表的bucket数设置为大表的倍数。这样数据就会按照key join,做hash bucket。小表依然复制到所有节点,Map join的时候,小表的每一组bucket加载成hashtable,与对应的一个大表bucket做局部join,这样每次只需要加载部分hashtable就可以了。

2.1.5.1 条件

set hive.optimize.bucketmapjoin = true;一个表的bucket数是另一个表bucket数的整数倍bucket列 == join列必须是应用在map join的场景中

注意:如果表不是bucket的,则只是做普通join。

2.1.6 SMB join

        全称Sort Merge Bucket Join。

2.1.6.1 作用

        大表对小表应该使用MapJoin来进行优化,但是如果是大表对大表,如果进行shuffle,那就非常可怕,第一个慢不用说,第二个容易出异常,此时就可以使用SMB Join来提高性能。SMB Join基于bucket-mapjoin的有序bucket,可实现在map端完成join操作,可以有效地减少或避免shuffle的数据量。SMB join的条件和Map join类似但又不同。        

2.1.6.2 条件

bucket mapjoinSMB joinset hive.optimize.bucketmapjoin = true;set hive.optimize.bucketmapjoin = true; set hive.auto.convert.sortmerge.join=true; set hive.optimize.bucketmapjoin.sortedmerge = true; set hive.auto.convert.sortmerge.join.noconditionaltask=true;一个表的bucket数是另一个表bucket数的整数倍大表的bucket数=大表bucket数bucket列 == join列Bucket 列 == Join 列 == sort 列必须是应用在map join的场景中必须是应用在bucket mapjoin 的场景中

2.1.6.3 注意事项

        hive并不检查两个join的表是否已经做好bucket且sorted,需要用户自己去保证join的表数据sorted,否则可能数据不正确。         有两个办法:

hive.enforce.sorting 设置为 true。开启强制排序时,插数据到表中会进行强制排序,默认false。插入数据时通过在sql中用distributed c1 sort by c1 或者 cluster by c1 另外,表创建时必须是CLUSTERED且SORTED,如下: create table test_smb_2(mid string,age_id string) CLUSTERED BY(mid) SORTED BY(mid) INTO 500 BUCKETS; 综上,涉及到分桶表操作的齐全配置为: --写入数据强制分桶 set hive.enforce.bucketing=true; --写入数据强制排序 set hive.enforce.sorting=true; --开启bucketmapjoin set hive.optimize.bucketmapjoin = true; --开启SMB Join set hive.auto.convert.sortmerge.join=true; set hive.auto.convert.sortmerge.join.noconditionaltask=true;

开启MapJoin的配置(hive.auto.convert.join和hive.auto.convert.join.noconditionaltask.size),还有限制对桶表进行load操作(hive.strict.checks.bucketing)可以直接设置在hive的配置项中,无需在sql中声明。 自动尝试SMB联接(hive.optimize.bucketmapjoin.sortedmerge)也可以在设置中进行提前配置。

3 Hive并行操作 3.1 Hive编译查询限制

        Hive默认同时只能编译一段HiveQL,并上锁。         将hive.driver.parallel.compilation设置为true,各个会话可以同时编译查询,提高团队工作效率。否则如果在UDF中执行了一段HiveQL,或者多个用户同时使用的话, 就会锁住。         修改hive.driver.parallel.compilation.global.limit的值,0或负值为无限制,可根据团队人员和硬件进行修改,以保证同时编译查询。

3.2 Hive不同阶段任务并行执行

        Hive会将一个查询转化为一个或多个阶段,包括:MapReduce阶段、抽样阶段、合并阶段、limit阶段等。默认情况下,一次只执行一个阶段。不过,如果某些阶段不是互相依赖,是可以并行执行的。  

set hive.exec.parallel=true; --可以开启并发执行,默认为false set hive.exec.parallel.thread.number=16; --同一个sql允许的最大并行度,默认为8 4 Hive索引

        Hive支持索引,但是Hive的索引与关系型数据库中的索引并不相同,比如,Hive不支持主键或者外键。         Hive索引可以建立在表中的某些列上,以提升一些操作的效率,例如减少MapReduce任务中需要读取的数据块的数量。         在可以预见到分区数据非常庞大的情况下,分桶和索引常常是优于分区的。而分桶由于SMB Join对关联键要求严格,所以并不是总能生效。

4.1 Hive索引

        Hive的索引目的是提高Hive表指定列的查询速度。         没有索引时,类似'WHERE tab1.col1 = 10' 的查询,Hive会加载整张表或分区,然后处理所有的rows,但是如果在字段col1上面存在索引时,那么只会加载和处理文件的一部分。         在每次建立、更新数据后,Hive索引不会自动更新,需要手动进行更新(重建索引以构建索引表),会触发一个mr job。         Hive索引使用过程繁杂,而且性能一般,在Hive3.0中已被删除,在工作环境中不推荐优先使用,在分区数量过多或查询字段不是分区字段时,索引可以作为补充方案同时使用。推荐使用ORC文件格式的索引类型进行查询。

4.2 Row Group Index

        一个ORC文件包含一个或多个stripes(groups of row data),每个stripe中包含了每个column的min/max值的索引数据,当查询中有,=的操作时,会根据min/max值,跳过扫描不包含的stripes。         而其中为每个stripe建立的包含min/max值的索引,就称为Row Group Index行组索引,也叫min-max Index大小对比索引,或者Storage Index。         在建立ORC格式表时,指定表参数’orc.create.index’=’true’之后,便会建立Row Group Index,需要注意的是,为了使Row Group Index有效利用,向表中加载数据时,必须对需要使用索引的字段进行排序,否则,min/max会失去意义。另外,这种索引主要用于数值型字段的查询过滤优化上。         设置hive.optimize.index.filter为true,并重启hive

创建表 CREATE TABLE lxw1234_orc2 stored AS ORC TBLPROPERTIES ( 'orc.compress'='SNAPPY', -- 开启行组索引 'orc.create.index'='true' ) AS SELECT CAST(siteid AS INT) AS id, pcid FROM lxw1234_text -- 插入的数据保持排序 DISTRIBUTE BY id sort BY id; 查询 set hive.optimize.index.filter=true; SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 1382 AND id = 0 AND id


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3