一、Hive-sql 常用优化

MapReduce 流程:

Input->split->map->buffer(此处调整其大小)->spill->spill过多合并->merge->combine(减少reduce压力)->shuffle(copy、merge)->spill->disk->reduce->Output

1.1、常用参数设置

#增加reducer任务数量(拉取数量分流)
set mapred.reduce.tasks=20; #在同一个sql中的不同的job是否可以同时运行,默认为false
set hive.exec.parallel=true; #增加同一个sql允许并行任务的最大线程数
set hive.exec.parallel.thread.number=8; #设置reducer内存大小
set mapreduce.reduce.memory.mb=4096;
set mapreduce.reduce.java.opts=-Xmx3584m; -- -Xmx 设置堆的最大空间大小。 #设置执行引擎
set hive.execution.engine=mr; -- 执行MapReduce任务,也可以设置为spark
-- 设置内存大小
set mapreduce.reduce.memory.mb=8192; -- reduce 设置的是 Container 的内存上限,这个参数由 NodeManager 读取并进行控制,当 Container 的内存大小超过了这个参数值,NodeManager 会负责 kill 掉 Container
set mapreduce.reduce.java.opts=-Xmx6144m; -- reduce Java 程序可以使用的最大堆内存数,要小于 mapreduce.reduce.memory.mb
set mapreduce.map.memory.mb=8192; -- map申请内存大小
set mapreduce.map.java.opts=-Xmx6144m; #动态分区设置,参考:https://www.cnblogs.com/cssdongl/p/6831884.html
set hive.exec.dynamic.partition=true; 是开启动态分区
set hive.exec.dynamic.partition.mode=nonstrict; 这个属性默认值是strict,就是要求分区字段必须有一个是静态的分区值,当前设置为nonstrict,那么可以全部动态分区 #其他
-- 开始负载均衡
set hive.groupby.skewindata=true
-- 开启map端combiner
set hive.map.aggr=true

1.2、mapjoin

#mapjoin相关设置,小表加载到内存,无reduce
set hive.mapjoin.smalltable.filesize=25000000; -- 刷入内存表的大小(字节)。注意:设置太大也不会校验,所以要根据自己的数据集调整
set hive.auto.convert.join = true; -- 开启mapjoin,默认false
set hive.mapjoin.followby.gby.localtask.max.memory.usage=0.6 ;--map join做group by操作时,可使用多大的内存来存储数据。若数据太大则不会保存在内存里,默认0.55
set hive.mapjoin.localtask.max.memory.usage=0.90; -- 本地任务可以使用内存的百分比,默认值:0.90
-- 在设置成false时,可以手动的指定mapjoin /*+ MAPJOIN(c) */ 。-->c:放到内存中的表
select /*+ MAPJOIN(c) */ * from user_install_status u
inner join country_dict c
on u.country=c.code
-- 如果不是做innerjoin, 做left join 、right join
-- A left join B, 把B放到内存
-- A right join B, 把A放到内存

1.3、小文件合并

产生原因:

  • hive动态分区插入数据,分区数据量小,产生大量的小文件
  • reduce数量越多,输出大量小文件
  • 数据源本身就就是一些小文件

影响:

  • MapReduce原理上理解,小文件会开很多map,一个map开一个JVM去执行,每个任务的初始化、启动、执行,都会消耗资源。
  • 在HDFS中,每个小文件对象约占150byte,如果小文件过多会占用大量内存。这样NameNode内存容量限制了集群规模。

解决方案:

在hive里有两种比较常见的处理办法

第一是使用Combinefileinputformat,将多个小文件打包作为一个整体的 inputsplit,减少map任务数

set mapred.max.split.size=256000000; # 每个 Map 最大分割大小

set mapred.min.split.size.per.node=256000000; # 一个节点上 split 的最小值

set  Mapred.min.split.size.per.rack=256000000; #一个交换机下 split的最小值

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; #执行 map 前进行小文件的合并

第二是设置hive参数,将额外启动一个MR Job打包小文件

set hive.merge.mapfiles = true; # 是否合并Map输出文件

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

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

1.4、JVM 重用

  • MapReduce 执行过程中每个任务/task 会启用一个 JVM 来执行 map 和 reduce 任务,这时 JVM 的启动过程可能会造成资源的消耗,如果一个job包含大量的task任务的情况,此优化效果比较明显。通过参数 mapred.job.reuse.jvm.num.tasks 来设置
  • 默认情况下,它被设置为 +1,这意味着每个 Map/Reduce 任务都会启动一个新的JVM 。 相反,如果将它设置为 -1,那么可以通过无限数量的任务来使用 jvm 。 在这种情况下,任务连续执行一个,以使用相同的JVM 。
  • 为每个task启动一个新的 JVM 将耗时1秒左右,对于运行时间较长(比如1分钟以上)的job影响不大,但如果都是时间很短的task,那么频繁启停JVM会有开销。
  • 如果我们想使用JVM重用技术来提高性能,那么可以将mapred.job.reuse.jvm.num.tasks设置成大于1的数。这表示属于同一job的顺序执行的task可以共享一个JVM,也就是说第二轮的map可以重用前一轮的JVM,而不是第一轮结束后关闭JVM,第二轮再启动新的JVM。
  • 注意:
    • JVM重用技术不是指同一Job的两个或两个以上的task可以同时运行于同一JVM上,而是排队按顺序执行。
    • 如果task属于不同的job,那么JVM重用机制无效,不同job的task需要不同的JVM来运行。

1.5、常见 sql 优化

  • 减少使用distinct
  • 查询条件中减少使用函数
  • 避免使用select *
  • 多个union all可以使用insert into替换
  • 尽量避免一个SQL包含复杂逻辑,可以使用中间表来完成复杂的逻辑
  • 减少每个阶段的数据量,对于分区表要加分区,同时只选择需要使用到的字段

二、数据倾斜

2.1、数据倾斜的表现

  • 任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成。因为其处理的数据量和其他reduce差异过大。
  • 单一reduce的记录数与平均记录数差异过大,通常可能达到3倍甚至更多。 最长时长远大于平均时长。

2.2、数据倾斜的解决方案

参数调节:

  • 对于group by 产生倾斜的问题

    • 开启map端combiner:【set hive.map.aggr=true;】
    • 开启负载均衡:【set hive.groupby.skewindata=true;】
      • 有数据倾斜的时候进行负载均衡,当选项设定为 true,生成的查询计划会有两个 MR Job。
      • 第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;
      • 第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

SQL 语句调节:

  • 大小表Join:

    • 使用map join让小的维度表先进内存。在map端完成join,不经过reduce。
  • 大表Join大表:
    • 非法数据太多,比如null,可以把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果。
    • 如果null值不要,可以通过where条件筛选掉;
    • 将大量的非法数据转化成随机数+字符串,这样两个表的数据不会join在一起。
  • count distinct大量相同特殊值:
    • count distinct时,将值为空的情况单独处理
    • 如果是计算count distinct,可以不用处理,直接过滤,在最后结果中加1。
    • 如果还有其他计算,需要进行group by,可以先将值为空的记录单独处理,再和其他计算结果进行union。
    • 采用sum group by的方式来替换 count(distinct) 完成计算。
  • 空值过多,集中到一个reduce处理--设置随机数(case when a.column is null then concat('test',rand()) else column end = b.column)或过滤。
  • 特殊情况特殊处理:
    • 在业务逻辑优化效果的不大情况下,有些时候是可以将倾斜的数据单独拿出来处理。最后union回去
    • 比如:group by时维度过小,数据过于集中,数据自身倾斜,比如 北京的用户比其它地方的用户多很多
    • 此时可以把北京的数据单独处理:先把北京的数据分成N块,每块的数据进行局部统计,再将每块的局部统计结果进行汇总,最终统计出结果

3、Hive-sql优化,数据倾斜处理的更多相关文章

  1. Hive中的数据倾斜

    Hive中的数据倾斜 hive 1. 什么是数据倾斜 mapreduce中,相同key的value都给一个reduce,如果个别key的数据过多,而其他key的较少,就会出现数据倾斜.通俗的说,就是我 ...

  2. hive优化-数据倾斜优化

    数据倾斜解决方法,通常从以下几个方面进行考量: 业务上丢弃  •  不参与关联:在on条件上直接过滤 •  随机数打散:比如 null.空格.0等“Other”性质的特殊值  倾斜键记录单独处理 •  ...

  3. 深入浅出Hive企业级架构优化、Hive Sql优化、压缩和分布式缓存(企业Hadoop应用核心产品)

    一.本课程是怎么样的一门课程(全面介绍)    1.1.课程的背景       作为企业Hadoop应用的核心产品,Hive承载着FaceBook.淘宝等大佬 95%以上的离线统计,很多企业里的离线统 ...

  4. Spark性能优化--数据倾斜调优与shuffle调优

    一.数据倾斜发生的原理 原理:在进行shuffle的时候,必须将各个节点上相同的key拉取到某个节点上的一个task来进行处理,比如按照key进行聚合或join等操作.此时如果某个key对应的数据量特 ...

  5. Hive、Inceptor数据倾斜详解及解决

    一.倾斜造成的原因 正常的数据分布理论上都是倾斜的,就是我们所说的20-80原理:80%的财富集中在20%的人手中, 80%的用户只使用20%的功能 , 20%的用户贡献了80%的访问量. 俗话是,一 ...

  6. spark 性能优化 数据倾斜 故障排除

    版本:V2.0 第一章       Spark 性能调优 1.1      常规性能调优 1.1.1   常规性能调优一:最优资源配置 Spark性能调优的第一步,就是为任务分配更多的资源,在一定范围 ...

  7. Hive SQL优化思路

    Hive的优化主要分为:配置优化.SQL语句优化.任务优化等方案.其中在开发过程中主要涉及到的可能是SQL优化这块. 优化的核心思想是: 减少数据量(例如分区.列剪裁) 避免数据倾斜(例如加参数.Ke ...

  8. hive单节点数据倾斜解决方法

    一.现象 map/reduce程序执行时,reduce节点大部分执行完毕,但是有一个或者几个reduce节点运行很慢,导致整个程序的处理时间很长,这是因为某一个key的条数比其他key多很多(有时是百 ...

  9. Hive SQL 优化面试题整理

    Hive优化目标 在有限的资源下,执行效率更高 常见问题: 数据倾斜 map数设置 reduce数设置 其他 Hive执行 HQL --> Job --> Map/Reduce 执行计划 ...

  10. hive SQL优化之distribute by和sort by

    近期在优化hiveSQL. 以下是一段排序,分组后取每组第一行记录的SQL INSERT OVERWRITE TABLE t_wa_funnel_distinct_temp PARTITION (pt ...

随机推荐

  1. 杭电 逃离迷宫 BFS

    给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位 ...

  2. python操作数据库-SQLSERVER-pyodbc

    刚开始学python时,大家都习惯用pymssql去读写SQLSERVER.但是实际使用过程中,pymssql的读写性能以及可靠性的确不如pyodbc来的好. 正如微软官方推荐使用pyodbc库,作为 ...

  3. 解决sublime打开文档,出现中文乱码问题

    sublime text 软件中出现中文乱码,大多是因为编码格式不支持,需要安装一个插件就可以解决中文乱码问题,推荐安装 ConvertToUtf8  安装步骤: 1.按“shift + ctrl + ...

  4. mysql查询添加

    当表结构一样的情况下,insert into 想要插入的表  SELECT * from  查询的表; 此sql语句,适应于 1000万数据插入1000万数据中去,2000万数据的合并 .------ ...

  5. 结构体 偏移量 (size_t)&(((s *)0)->m) , list相关

    在Windows SDK 的stddef.h 中 #define offsetof(s,m) (size_t)&(((s *)0)->m) 应用例如 #define list_conta ...

  6. Shutdown SpringBoot App

    文章目录 Shutdown Endpoint close Application Context 退出SpringApplication 从外部程序kill App Shutdown SpringBo ...

  7. Libra教程之:运行自定义move modules

    文章目录 简介 创建Move modules 启动本地网络 创建账号并送测试币 编译Move Module 发布编译好的Module 创建交易脚本 编译编译脚本 执行脚本 简介 因为Libra和Mov ...

  8. 第八章服务器raid及配置实战

      版本 特点 磁盘个数 可用空间 故障磁盘数 应用环境 RAID0 读写速度快,数据容易丢失 两个 全部 一块 测试,临时性 RAID1 读写速度慢,数据可靠 至少两个,可以2的倍数 总容量的一半 ...

  9. 写给Java程序员的Java虚拟机学习指南

    大家好,我是极客时间<深入拆解Java虚拟机>作者.Oracle Labs高级研究员郑雨迪.有幸借这个专题的机会,能和大家分享为何Java工程师要学Java虚拟机?如何掌握Java虚拟机? ...

  10. 《SQL初学者指南》——第1章 关系型数据库和SQL

    第1章 关系型数据库和SQL SQL初学者指南在本章中,我们将介绍一些背景知识,以便于你能够很快地上手,能在后续的章节中编写SQL语句.本章有两个主题.首先是对本书所涉及到的数据库做一个概述,并且介绍 ...