ToB企服应用市场:ToB评测及商务社交产业平台

标题: Hive 调优(包罗hive全部调优方式 看这一篇就够了) [打印本页]

作者: 万有斥力    时间: 2024-7-15 16:14
标题: Hive 调优(包罗hive全部调优方式 看这一篇就够了)
Hive 调优

hive官方设置url: https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties
1、调优方式

  1. hive参数配置的意义: 开发Hive应用/调优时,不可避免地需要设定Hive的参数。设定Hive的参数可以调优HQL代码的执行效率,或帮助定位问题。然而实践中经常遇到的一个问题是,为什么我设定的参数没有起作用?这是对hive参数配置几种方式不了解导致的!
  2. hive参数设置范围(从大到小): 配置文件 > 命令行参数 > set参数声明
  3. hive参数设置优先级(从高优先级到低优先级): set参数声明 > 命令行参数 > 配置文件
  4. 注意: 在工作中,推荐使用set参数声明,因为最简单最方便。而且同一个大数据集群除了你了还有其他的人或者项目组在使用。
复制代码
2、hive数据压缩

Hive底层是运行MapReduce,以是Hive支持什么压缩格式本质上取决于MapReduce。
2.1 压缩对比

   在后续可能会使用GZ(GZIP), 包管压缩后的数据更小, 同时压缩和解压的速度比较OK的,
  但是大部门的选择重要会选择另一种压缩方案, snappy, 此种方案可以包管在公道的压缩比下, 拥有更高的解压缩的速度,在大数据领域中重要是关注数据的处理速度
  http://google.github.io/snappy/
On a single core of a Core i7 processor in 64-bit mode, Snappy compresses at about 250 MB/sec or more and decompresses at about 500 MB/sec or more.
  

2.2 开启压缩

   开启map输出阶段压缩可以减少job中map和Reduce task间数据传输量. 当Hive将输出写入到表中时,输出内容同样可以举行压缩。用户可以通过在查询语句或执行脚本中设置这个值为true,来开启输出效果压缩功能。
  1. -- 创建数据库
  2. create database hive05;
  3. -- 使用库
  4. use hive05;
  5. -- 开启压缩(map阶段或者reduce阶段)
  6. --开启hive支持中间结果的压缩方案
  7. set hive.exec.compress.intermediate; -- 查看默认
  8. set hive.exec.compress.intermediate=true ;
  9. --开启hive支持最终结果压缩
  10. set hive.exec.compress.output; -- 查看默认
  11. set hive.exec.compress.output=true;
  12. --开启MR的map端压缩操作
  13. set mapreduce.map.output.compress; -- 查看默认
  14. set mapreduce.map.output.compress=true;
  15. --设置mapper端压缩的方案
  16. set mapreduce.map.output.compress.codec; -- 查看默认
  17. set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;
  18. -- 开启MR的reduce端的压缩方案
  19. set mapreduce.output.fileoutputformat.compress; -- 查看默认
  20. set mapreduce.output.fileoutputformat.compress=true;
  21. -- 设置reduce端压缩的方案
  22. set mapreduce.output.fileoutputformat.compress.codec; -- 查看默认
  23. set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
  24. --设置reduce的压缩类型
  25. set mapreduce.output.fileoutputformat.compress.type; -- 查看默认
  26. set mapreduce.output.fileoutputformat.compress.type=BLOCK;
复制代码
3、hive数据存储

3.1 行列存储原理



  1. 行存储的特点: 将数据以行的形式整体进行存放
  2. 列存储的特点: 将相同字段的值作为整体放在一起进行存放
  3. 行存储:
  4.         优点: 如果要查询整行数据内容,速度比较快。适合进行数据的insert/update操作
  5.         缺点: 如果数据分析的时候,只想针对某几个字段进行处理,那么这个效率低。因为会将不需要的字段内容也会加载出来
  6.         使用: textfile和sequencefile
  7.        
  8. 列存储:
  9.         优点: 如果数据分析的时候,只想针对某几个字段进行处理,那么效率高,因为你要什么,我就给你返回什么
  10.         缺点: 如果要查询整行数据内容,速度比较慢。不适合进行数据的insert/update操作
  11.         使用: orc和parquet。推荐使用orc
  12.        
  13. 注意: 在工作中推荐ORC+Snappy压缩一起使用,更加能够减少HDFS的磁盘占用。
  14. 格式:
  15.         stored as orc -- 设置数据的存储格式
  16.         tblproperties ("orc.compress"="SNAPPY"); -- 设置数据的压缩格式
复制代码
ORC

3.2 存储压缩比

  1. -- 数据的存储和压缩方式
  2. -- textfile:占用空间18.13 MB(如果是HDFS需要乘以3)
  3. create table log_text(
  4.     track_time string,
  5.     url string,
  6.     session_id string,
  7.     referer string,
  8.     ip string,
  9.     end_user_id string,
  10.     city_id string
  11. )
  12. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
  13. stored as textfile; -- 表默认的存储格式就是不压缩并且使用行式存储中的textfile存储
  14. -- 导入数据
  15. load data inpath '/dir/log.data' into table log_text;
  16. -- 数据验证
  17. select * from log_text;
  18. select count(*) as cnt from log_text;
  19. -- 列式存储:ORC,占用空间2.78 MB
  20. create table log_orc(
  21.     track_time string,
  22.     url string,
  23.     session_id string,
  24.     referer string,
  25.     ip string,
  26.     end_user_id string,
  27.     city_id string
  28. )
  29. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
  30. stored as orc;
  31. -- 加载数据
  32. insert overwrite table log_orc select * from log_text;
  33. select count(*) as cnt from log_orc;
  34. -- 列式存储:ORC+snappy。占用空间3.75 MB,这里相对ORC反而多占用了1MB空间,是因为数据量太小,同时压缩以后,压缩文件里面需要存储和压缩相关元数据信息(例如:使用的压缩算法具体是哪一个)
  35. -- https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL
  36. create table log_orc_snappy(
  37.     track_time string,
  38.     url string,
  39.     session_id string,
  40.     referer string,
  41.     ip string,
  42.     end_user_id string,
  43.     city_id string
  44. )
  45. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
  46. stored as orc -- 设置数据的存储格式
  47. tblproperties ("orc.compress"="SNAPPY"); -- 设置数据的压缩格式
  48. -- 加载数据
  49. insert overwrite table log_orc_snappy select * from log_text;
  50. select count(*) as cnt from log_orc_snappy;
  51. -- 列式存储:parquet。占用空间13.09MB
  52. create table log_orc_parquet(
  53.     track_time string,
  54.     url string,
  55.     session_id string,
  56.     referer string,
  57.     ip string,
  58.     end_user_id string,
  59.     city_id string
  60. )
  61. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
  62. stored as parquet;
  63. -- 加载数据
  64. insert overwrite table log_orc_parquet select * from log_text;
  65. select count(*) as cnt from log_orc_parquet;
复制代码
  拓展dfs -du -h
  1. -- 查看hdfs文件大小除了去页面查看,还可以通过命令
  2. dfs -du -h '/user/hive/warehouse/hive05.db/log_text/log.data' ;
  3. dfs -du -h '/user/hive/warehouse/hive05.db/log_orc/000000_0' ;
  4. dfs -du -h '/user/hive/warehouse/hive05.db/log_orc_snappy/000000_0' ;
  5. dfs -du -h '/user/hive/warehouse/hive05.db/log_parquet/000000_0' ;
复制代码
4、fetch抓取

核心点: 在执行SQL, 能不走MR, 尽量不走MR
追念, 在之前执行什么样查询的SQL的时候,没有走MR呢?
  1. 1) 全表扫描
  2. 2) 查询某个列数据
  3. 3) 执行一些简单查询操作
  4. 4) 执行limit操作
复制代码
而这些操作, 没有走MR原因, 就是hive默认以及开启本地抓取的策略方案:
  1. hive.fetch.task.conversion:   设置本地抓取策略
  2. 可选:
  3.         more (默认值): 可以保证在执行全表扫描、查询某几个列、简单的limit查询、简单的条件过滤不会变成MapReduce
  4.         minimal: 可以保证在执行全表扫描、查询某几个列、简单的limit查询不会变成MapReduce
  5.         none: 全部的HiveSQL语句都要变成MapReduce
复制代码
示例:
  1. -- 不会变成MapReduce几类SQL演示
  2. -- 默认是more,底层自动调优
  3. set hive.fetch.task.conversion;  -- 默认值more
  4. select * from log_text; -- 全表扫描
  5. select url from log_text; -- 查询某个列的数据
  6. select * from log_text where city_id=-10; -- 简单的where过滤查询
  7. select * from log_text limit 10; -- 执行limit程序
  8. select * from log_text order by url desc limit 100,10; -- 复杂limit会变成MapReduce
  9. set hive.fetch.task.conversion=minimal;
  10. set hive.fetch.task.conversion;
  11. select * from log_text; -- 全表扫描
  12. select url from log_text; -- 查询某个列的数据
  13. select * from log_text limit 10; -- 执行limit程序
  14. select * from log_text where city_id=-10; -- 简单的where过滤查询
  15. set hive.fetch.task.conversion=none;
  16. set hive.fetch.task.conversion; -- 这里也要变成MapReduce
  17. select * from log_text; -- 全表扫描
  18. select url from log_text; -- 查询某个列的数据
  19. select * from log_text limit 10; -- 执行limit程序
  20. select * from log_text where city_id=-10; -- 简单的where过滤查询
复制代码
5、本地模式

核心点:让MR能走本地模式, 尽量走本地MR(明确话: 小活能自己干就不要麻烦别人)
  1. 如何开启:
  2.         set hive.exec.mode.local.auto=true;  默认值为: false
  3. 开启本地模式后, 在什么情况下执行本地MR:   只有当输入的数据满足以下两个特性后, 才会执行本地MR
  4.         set hive.exec.mode.local.auto.inputbytes.max=51234560;   
  5.                 默认为128M。设置本地MR最大处理的数据量
  6.         set hive.exec.mode.local.auto.input.files.max=10;
  7.                 默认值为4。设置本地MR最大处理的文件的数量
复制代码
示例:
  1. -- 4.开启本地mr(默认false,如果小数据任务进行调优开启,小任务能自己干就自己干)
  2. set hive.exec.mode.local.auto;  -- 默认关闭
  3. set hive.exec.mode.local.auto=false; -- 手动关闭
  4. set hive.exec.mode.local.auto=true; -- 手动开启
  5. --设置local mr的最大输入数据量,当输入数据量小于这个值时采用local  mr的方式,默认为134217728,即128M
  6. set hive.exec.mode.local.auto.inputbytes.max;-- 查看
  7. set hive.exec.mode.local.auto.inputbytes.max=134217728;
  8. --设置local mr的最大输入文件个数,当输入文件个数小于这个值时采用local mr的方式,默认为4
  9. set hive.exec.mode.local.auto.input.files.max;-- 查看
  10. set hive.exec.mode.local.auto.input.files.max=4;
  11. -- 执行sql语句
  12. -- 没有开启本地执行24秒,开启后1.5秒
  13. select * from log_text order by city_id desc;
  14. -- 注意: 有的同学开启本地模式后执行上述sql语句,会报code 2...错误
  15. -- 错误:[08S01][2] Error while processing statement: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
  16. -- 如何解决? /export/server/hive/hive-env.sh  修改 export HADOOP_HEAPSIZE=2048
  17. -- 注意: 修改完后需要重启hive服务
复制代码
6、join的优化操作

思考: 在通过hive执行多表查询的SQL, 最终hive翻译的MR,是如何完成join的工作的呢?
默认的join举动, 基于reduce端的join工作
思考, 请问上述join存在哪些问题?
  1. 1) 导致reduce的压力剧增, 所有的数据全部都打向reduce中
  2. 2) 当有了多个reduce后, 如果某个join字段的值出现大量的重复, 会导致大量key发往同一个reduce, 从而导致数据倾斜
复制代码
那么如何解决reduce端join遇到问题? 可以通过底层map 端 join实现,还可以sql语句join之条件前过滤数据或者转换数据实现
  1. 通过 map join 即可解决掉 reduce join所出现的所有的问题, 也可以这么 mapjoin有解决数据倾斜的作用
  2. 存在什么弊端:
  3.         小表数据需要存储在内存中, 随着mapTask越多, 存储在内存的小表数据份数也会越多
  4.                 当这个小表数据比较大的, 可能无法放置到内存中
  5. 所以说, mapJoin有一定使用范围: 仅适用于小表 和大表 进行join的情况
复制代码

7、列裁剪

Hive在读数据的时候,可以只读取查询中所必要用到的列,而忽略其他列
比方:
  1. 假设有一个表A: a b c d e   5个字段, 请查看以下SQL
  2. select  a,b from A where a=xxx;
  3. 在这条SQL, 发现没有使用c d e 字段, 在from A表时候, 读取数据, 只需要将a列 和 b列数据读取出来即可, 不需要读取cde列字段, 这样可以减少读取的数据量, 从而提升效率
复制代码
如何设置呢?
  1. -- -=【列裁剪(只读取sql语句需要的字段,节省读取开销,提升效率)
  2. set hive.optimize.cp=true;  -- 默认就是true  (在hive 2.x中无需在配置了, 直接为固定值: true)
复制代码
8、分区裁剪

执行查询SQL的时候, 能在join之条件前举行条件过滤的操作, 肯定要提前过滤, 不要在join后举行过滤操作
如果操作的表是一张分区表, 那么建议肯定要带上分区字段, 以减少扫描的数据量, 从而提升效率,
比方:
  1. select  * from A join B where A.id=xxx;
  2. 优化后:
  3. select * from (select * from A where id= xxx) A join B;
复制代码
如何设置呢?
  1. -- 7.分区裁剪
  2. set hive.optimize.pruner=true; --默认为就是true (在hive 2.x中无需在配置了, 直接为固定值: true)
复制代码
9、group by 操作

  1. 方案一:  
  2.     (1)是否在Map端进行聚合,默认为True
  3.     set hive.map.aggr = true;
  4.     (2)在Map端进行聚合操作的条目数目
  5.     set hive.groupby.mapaggr.checkinterval = 100000;
  6. 方案二:  官方称为 负载均衡
  7.     (3)有数据倾斜的时候进行负载均衡(默认是false)
  8.     set hive.groupby.skewindata = true;
  9.     第一个MR Job中,Map的输出结果会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;
  10.     第二个MR Job再根据预处理的数据结果按照Group By Key分布到Reduce中(这个过程可以保证相同的Group By Key被分布到同一个Reduce中),最后完成最终的聚合操作。
复制代码
10、count(distinct)

说明 : count(distinct) 在数据量比较大的情况下, 效率并不高
思考: 你知道是为什么吗?
  1. 原因如下:
  2.         请问1: 执行count操作的时候, hive翻译的MR, reduce数量是否可以有多个? 必然不会有多个, 只能有一个, 因为全局求最终结果
  3.         此时如果执行统计的时候, 需要进行去重,那么去重工作是由reduce执行去重操作,  由于reduce只有一个, 所有的数据都在一个reduce中, 此时reduce的压力比较大
  4.                
  5.         希望执行去重工作可能有多个reduce一起来执行操作, 此时可以将SQL优化:
  6.                 原有:
  7.                         select count(distinct ip) from ip_tab;
  8.                 优化:
  9.                         select
  10.                             count(ip)
  11.                         from
  12.                            (select ip from ip_tab group by ip) tmp;
  13.        
  14.                 请注意: 这样的做法, 虽然会运行两个MR, 但是当数据量足够庞大的时候, 此操作绝对是值得的, 如果数据量比较少, 此操作效率更低
复制代码
  1. -- count(distinct)优化
  2. set hive.optimize.countdistinct; -- 默认就是true
  3. set hive.optimize.countdistinct = true;
  4. /*
  5. SELECT count(DISTINCT id) FROM 大表;
  6. 结果:
  7. SELECT count(id) FROM (SELECT id FROM 大表 GROUP BY id) a;
  8. */
  9. select count(distinct devicetype) from device1;
  10. select count(devicetype) from (select devicetype from device1 group by devicetype) a;
  11. -- 注意: 小表拆分两个mr反而效率低,以后大表的时候才会真正提升效率
复制代码
11、笛卡尔积

什么是笛卡尔积呢? 在举行join的时候, 两个表乘积之后效果就是笛卡尔积的效果
比如: 一个表有5条, 一个表有3条数据, 笛卡尔积效果就有15条数据 , 笛卡尔积中有大量数据都是无用数据
什么时候会产生笛卡尔积呢?
在多表join的时候, 关联条件缺少或者使用错误的关联条件以及将关联条件放置在where中都会导致笛卡尔积
12、动态分区

需求: 请将下面的一个分区表数据, 拷贝到另一个分区表, 包管对应区数据放置到另一个表的对应区下
如何设置呢?
  1. 作用:  帮助一次性灌入多个分区的数据
  2. 参数:
  3.         set hive.exec.dynamic.partition.mode=nonstrict;  -- 开启非严格模式 默认为 strict(严格模式)
  4.         set hive.exec.dynamic.partition=true;  -- 开启动态分区支持, 默认就是true
  5.        
  6. 可选的参数:
  7.         set  hive.exec.max.dynamic.partitions=1000; -- 在所有执行MR的节点上,最大一共可以创建多少个动态分区。
  8.         set hive.exec.max.dynamic.partitions.pernode=100; -- 每个执行MR的节点上,最大可以创建多少个动态分区
  9.         set hive.exec.max.created.files=100000; -- 整个MR Job中,最大可以创建多少个HDFS文件
复制代码
13、如何调整map和reduce的数量

   1>是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。
  2>是不是包管每个map处理靠近128m的文件块,就高枕无忧了?
答案也是不肯定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。
  3>是不是reduce数越多越好?
答案是否定的。如果reduce设置的过大,对整个作业会产生肯定的影响。
①过多的启动和初始化reduce也会消耗时间和资源;
②另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
  4>在什么情况下, 只能有一个reduce呢?
  以下几种, 不管如何设置, 最终翻译后reduce只能有一个
​ 1) 执行order by操作
​ 2) 执行不必要group by直接聚合的操作
​ 3) 执行笛卡尔积
  
14、并行执行

​ 在执行一个SQL语句的时候, SQL会被翻译为MR, 一个SQL有可能被翻译成多个MR, 那么在多个MR之间, 有些MR之间可能不存在任何的关联, 此时可以设置让这些没有关联的MR 并行执行, 从而提升效率 , 默认是 一个一个来
如何设置:
  1. set hive.exec.parallel=false;              --打开任务并行执行,默认关闭
  2. set hive.exec.parallel.thread.number=8;  --同一个sql允许最大并行度,默认为8。
  3. 前提:
  4.         服务器必须有资源, 如果没有 即使支持并行, 也没有任何作用
复制代码
案例:
  1. select  * from A ....
  2. union all
  3. select * from B ...;
  4. 例如:
  5.         select from (select * from A group by ...) tmp1 join (select * from B group by xxx) on ...
复制代码
15、严格模式

​ hive提供一种严格模式, 重要目的, 是为了限定一些 效率极低的SQL 放置其执行时间过长, 影响其他的操作
  1. 屏蔽一下操作:
  2. 1) 执行order by 不加 limit
  3. 2) 出现笛卡尔积的现象SQL
  4. 3) 查询分区表, 不带分区字段
  5. 前提: 数据量足够大, 如果数据量比较少, 严格模式对此三项内容不生效
复制代码
如何设置:
  1. set hive.mapred.mode = strict;  --开启严格模式
  2. set hive.mapred.mode = nostrict; --开启非严格模式   最新默认
复制代码
16、JVM 重用

此操作, 在hive2.x已经不必要设置了, 默认支持
  1. jvm重用: 默认情况下, container资源容器  只能使用一次,不能重复使用, 开启JVM重用, 运行container容器可以被重复使用,在hive2.x已经默认支持了
复制代码
17、推测执行

  1. Hadoop采用了推测执行(Speculative Execution)机制,它根据一定的法则推测出“拖后腿”的任务,并为这样的任务启动一个备份任务,让该任务与原始任务同时处理同一份数据,并最终选用最先成功运行完成任务的计算结果作为最终结果。
  2. hadoop中默认两个阶段都开启了推测执行机制。
  3. hive本身也提供了配置项来控制reduce-side的推测执行:
  4. set hive.mapred.reduce.tasks.speculative.execution=true;
  5. 关于调优推测执行机制,还很难给一个具体的建议。如果用户对于运行时的偏差非常敏感的话,那么可以将这些功能关闭掉。如果用户因为输入数据量很大而需要执行长时间的map或者Reduce task的话,那么启动推测执行造成的浪费是非常巨大。
复制代码
18、执行计划explain

  1. 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。帮助我们了解底层原理,hive调优,排查数据倾斜等有很有帮助
  2. 使用示例:explain [...]  sql查询语句;
  3. explain sql语句: 查看执行计划的基本信息
复制代码

  1. (1)stage dependencies:各个stage之间的依赖性
  2. 包含多个stage阶段,例如 Stage-1和Stage-0,Stage-1 是根stage,Stage-0 依赖 Stage-1,
  3. (2)stage plan:各个stage的执行计划
  4. 包含两部分: map端执行计划树和reduce端执行计划树
复制代码
ks.speculative.execution=true;
关于调优推测执行机制,还很难给一个具体的建议。如果用户对于运行时的偏差非常敏感的话,那么可以将这些功能关闭掉。如果用户由于输入数据量很大而必要执行长时间的map或者Reduce task的话,那么启动推测执行造成的浪费是非常巨大。
  1. ## 18、执行计划explain使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。帮助我们了解底层原理,hive调优,排查数据倾斜等有很有帮助
  2. 使用示例:explain [...]  sql查询语句;
  3. explain sql语句: 查看执行计划的基本信息
复制代码
[外链图片转存中…(img-33z4aUG4-1715785755032)]
  1. (1)stage dependencies:各个stage之间的依赖性
  2. 包含多个stage阶段,例如 Stage-1和Stage-0,Stage-1 是根stage,Stage-0 依赖 Stage-1,
  3. (2)stage plan:各个stage的执行计划
  4. 包含两部分: map端执行计划树和reduce端执行计划树
复制代码


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4