Hive参数与性能调优-V2.0

Hive作为大数据平台举足轻重的框架,以其稳定性和简单易用性也成为当前构建企业级数据仓库时使用最多的框架之一。

但是如果我们只局限于会使用Hive,而不考虑性能问题,就难搭建出一个完美的数仓,所以Hive性能调优是我们大数据从业者必须掌握的技能。本文将给大家讲解Hive性能调优的一些方法及技巧。

一、Hive性能调优的方式

为什么都说性能优化这项工作是比较难的,因为一项技术的优化,必然是一项综合性的工作,它是多门技术的结合。我们如果只局限于一种技术,那么肯定做不好优化的。

下面将从多个完全不同的角度来介绍Hive优化的多样性,我们先来一起感受下。

1. SQL语句优化

SQL语句优化涉及到的内容太多,因篇幅有限,不能一一介绍到,所以就拿几个典型举例,让大家学到这种思想,以后遇到类似调优问题可以往这几个方面多思考下。

1. union all

insert into table stu partition(tp) 
select s_age,max(s_birth) stat,'max' tp 
from stu_ori
group by s_ageunion allinsert into table stu partition(tp) 
select s_age,min(s_birth) stat,'min' tp 
from stu_ori
group by s_age;

我们简单分析上面的SQl语句,就是将每个年龄的最大和最小的生日获取出来放到同一张表中,union all 前后的两个语句都是对同一张表按照s_age进行分组,然后分别取最大值和最小值。对同一张表相同的字段进行两次分组,这造成了极大浪费,我们能不能改造下呢,当然是可以的,为大家介绍一个语法:from ... insert into ... ,这个语法将from前置,作用就是使用一张表,可以进行多次插入操作:

--开启动态分区 
set hive.exec.dynamic.partition=true; 
set hive.exec.dynamic.partition.mode=nonstrict; from stu_ori insert into table stu partition(tp) 
select s_age,max(s_birth) stat,'max' tp 
group by s_ageinsert into table stu partition(tp) 
select s_age,min(s_birth) stat,'min' tp 
group by s_age;

上面的SQL就可以对stu_ori表的s_age字段分组一次而进行两次不同的插入操作。

这个例子告诉我们一定要多了解SQL语句,如果我们不知道这种语法,一定不会想到这种方式的

2. distinct

先看一个SQL,去重计数:

select count(1) 
from( select s_age from stu group by s_age 
) b;

这是简单统计年龄的枚举值个数,为什么不用distinct?

select count(distinct s_age) 
from stu;

有人说因为在数据量特别大的情况下使用第一种方式能够有效避免Reduce端的数据倾斜,但是事实如此吗?

我们先不管数据量特别大这个问题,就当前的业务和环境下使用distinct一定会比上面那种子查询的方式效率高。原因有以下几点:

  1. 上面进行去重的字段是年龄字段,要知道年龄的枚举值是非常有限的,就算计算1岁到100岁之间的年龄,s_age的最大枚举值才是100,如果转化成MapReduce来解释的话,在Map阶段,每个Map会对s_age去重。由于s_age枚举值有限,因而每个Map得到的s_age也有限,最终得到reduce的数据量也就是map数量*s_age枚举值的个数。

  2. distinct的命令会在内存中构建一个hashtable,查找去重的时间复杂度是O(1);group by在不同版本间变动比较大,有的版本会用构建hashtable的形式去重,有的版本会通过排序的方式, 排序最优时间复杂度无法到O(1)。另外,第一种方式(group by)去重会转化为两个任务,会消耗更多的磁盘网络I/O资源。

  3. 最新的Hive 3.0中新增了 count(distinct ) 优化,通过配置 hive.optimize.countdistinct,即使真的出现数据倾斜也可以自动优化,自动改变SQL执行的逻辑。

  4. 第二种方式(distinct)比第一种方式(group by)代码简洁,表达的意思简单明了,如果没有特殊的问题,代码简洁就是优!

这个例子告诉我们,有时候我们不要过度优化,调优讲究适时调优,过早进行调优有可能做的是无用功甚至产生负效应,在调优上投入的工作成本和回报不成正比。调优需要遵循一定的原则

2. 数据格式优化

Hive提供了多种数据存储组织格式,不同格式对程序的运行效率也会有极大的影响。

Hive提供的格式有TEXT、SequenceFile、RCFile、ORC和Parquet等。

SequenceFile是一个二进制key/value对结构的平面文件,在早期的Hadoop平台上被广泛用于MapReduce输出/输出格式,以及作为数据存储格式。

Parquet是一种列式数据存储格式,可以兼容多种计算引擎,如MapRedcue和Spark等,对多层嵌套的数据结构提供了良好的性能支持,是目前Hive生产环境中数据存储的主流选择之一。

ORC优化是对RCFile的一种优化,它提供了一种高效的方式来存储Hive数据,同时也能够提高Hive的读取、写入和处理数据的性能,能够兼容多种计算引擎。事实上,在实际的生产环境中,ORC已经成为了Hive在数据存储上的主流选择之一。

我们使用同样数据及SQL语句,只是数据存储格式不同,得到如下执行时长:

数据格式CPU时间用户等待耗时
TextFile33分171秒
SequenceFile38分162秒
Parquet2分22秒50秒
ORC1分52秒56秒

注:CPU时间:表示运行程序所占用服务器CPU资源的时间。
用户等待耗时:记录的是用户从提交作业到返回结果期间用户等待的所有时间。

查询TextFile类型的数据表CPU耗时33分钟, 查询ORC类型的表耗时1分52秒,时间得以极大缩短,可见不同的数据存储格式也能给HiveSQL性能带来极大的影响。

3. 小文件过多优化

小文件如果过多,对 hive 来说,在进行查询时,每个小文件都会当成一个块,启动一个Map任务来完成,而一个Map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的Map数量是受限的。

所以我们有必要对小文件过多进行优化,关于小文件过多的解决的办法,我之前专门写了一篇文章讲解,具体可查看:

解决hive小文件过多问题

4. 并行执行优化

Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执行过程中可能需要的其他阶段。默认情况下,Hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段可能并非完全互相依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整个job的执行时间缩短。如果有更多的阶段可以并行执行,那么job可能就越快完成。

通过设置参数hive.exec.parallel值为true,就可以开启并发执行。在共享集群中,需要注意下,如果job中并行阶段增多,那么集群利用率就会增加。

set hive.exec.parallel=true; //打开任务并行执行
set hive.exec.parallel.thread.number=16; //同一个sql允许最大并行度,默认为8。

当然得是在系统资源比较空闲的时候才有优势,否则没资源,并行也起不来。

5. 数据倾斜优化

数据倾斜的原理都知道,就是某一个或几个key占据了整个数据的90%,这样整个任务的效率都会被这个key的处理拖慢,同时也可能会因为相同的key会聚合到一起造成内存溢出。

Hive的数据倾斜一般的处理方案

常见的做法,通过参数调优:

set hive.map.aggr=true;  
set hive.groupby.skewindata = ture;

当选项设定为true时,生成的查询计划有两个MapReduce任务。

在第一个MapReduce中,map的输出结果集合会随机分布到reduce中,每个reduce做部分聚合操作,并输出结果。

这样处理的结果是,相同的Group By Key有可能分发到不同的reduce中,从而达到负载均衡的目的;

第二个MapReduce任务再根据预处理的数据结果按照Group By Key分布到reduce中(这个过程可以保证相同的Group By Key分布到同一个reduce中),最后完成最终的聚合操作。

但是这个处理方案对于我们来说是个黑盒,无法把控。

那么在日常需求的情况下如何处理这种数据倾斜的情况呢:

  1. sample采样,获取哪些集中的key;

  2. 将集中的key按照一定规则添加随机数;

  3. 进行join,由于打散了,所以数据倾斜避免了;

  4. 在处理结果中对之前的添加的随机数进行切分,变成原始的数据。

例:如发现有90%的key都是null,数据量一旦过大必然出现数据倾斜,可采用如下方式:

SELECT *
FROM aLEFT JOIN b ON CASE WHEN a.user_id IS NULL THEN concat('hive_', rand())ELSE a.user_idEND = b.user_id;

注意:给null值随机赋的值不要与表中已有的值重复,不然会导致结果错误。

6. Limit 限制调整优化

一般情况下,Limit语句还是需要执行整个查询语句,然后再返回部分结果。

有一个配置属性可以开启,避免这种情况:对数据源进行抽样

hive.limit.optimize.enable=true -- 开启对数据源进行采样的功能

hive.limit.row.max.size -- 设置最小的采样容量

hive.limit.optimize.limit.file -- 设置最大的采样样本数

缺点:有可能部分数据永远不会被处理到

7. JOIN优化

1. 使用相同的连接键

当对3个或者更多个表进行join连接时,如果每个on子句都使用相同的连接键的话,那么只会产生一个MapReduce job。

2. 尽量尽早地过滤数据

减少每个阶段的数据量,对于分区表要加分区,同时只选择需要使用到的字段。

3. 尽量原子化操作

尽量避免一个SQL包含复杂逻辑,可以使用中间表来完成复杂的逻辑。

8. 谓词下推优化

Hive中的 Predicate Pushdown 简称谓词下推,简而言之,就是在不影响结果的情况下,尽量将过滤条件下推到join之前进行。谓词下推后,过滤条件在map端执行,减少了map端的输出,降低了数据在集群上传输的量,节约了集群的资源,也提升了任务的性能。

我们看下面这个语句:

select s1.key, s2.key 
from s1 left join s2 
on s1.key > '2';

上面是一个Left Join语句,s1是左表,称为保留行表,s2是右表。

:on条件的s1.key > '2' 是在join之前执行还是之后?也就是会不会进行谓词下推?

:不会进行谓词下推,因为s1是保留行表,过滤条件会在join之后执行。

而下面这个语句:

select s1.key, s2.key 
from s1 left join s2 
on s2.key > '2';

s2表不是保留行,所以s2.key>2条件可以下推到s2表中,也就是join之前执行。

再看下面这个语句:

select s1.key, s2.key 
from s1 left join s2 
where s1.key > '2';

右表s2为NULL补充表。

s1不是NULL补充表,所以s1.key>2可以进行谓词下推。

而下面语句:

select s1.key, s2.key 
from s1 left join s2 
where s2.key > '2';

由于s2为NULL补充表,所以s2.key>2过滤条件不能下推。

那么谓词下推的规则是什么,到底什么时候会进行下推,什么时候不会下推,总结了下面的一张表,建议收藏保存

图片

案例

select a.*  
from a  
left join b on  a.uid = b.uid  
where a.ds='2020-08-10'  
and b.ds='2020-08-10'

上面这个SQL主要犯了两个错误

  1. 右表(上方b表)的where条件写在join后面,会导致先全表关联在过滤分区。

注:虽然a表的where条件也写在join后面,但是a表会进行谓词下推,也就是先执行where条件,再执行join,但是b表不会进行谓词下推!

  1. on的条件没有过滤null值的情况,如果两个数据表存在大批量null值的情况,会造成数据倾斜。

二、最后

代码优化原则:

  • 理透需求原则,这是优化的根本;

  • 把握数据全链路原则,这是优化的脉络;

  • 坚持代码的简洁原则,这让优化更加简单;

  • 没有瓶颈时谈论优化,这是自寻烦恼。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/80409.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源库源码分析:OkHttp源码分析(二)

开源库源码分析:OkHttp源码分析(二) 导言 上一篇文章中我们已经分析到了OkHttp对于网络请求采取了责任链模式,所谓责任链模式就是有多个对象都有机会处理请求,从而避免请求发送者和接收者之间的紧密耦合关系。这篇文章…

vue学习之element-ui组件集成

1. element-ui 链接 https://element.eleme.cn/#/zh-CN 2. element-ui 安装 cnpm install element-ui3. 创建项目 https://blog.csdn.net/qq_36940806/article/details/132921688?spm=1001.2014.3001.5502 4. 引入element库 /src/main.js 引入 element-uiimport Vue from…

基于SSM+Vue的汽车售票网站的设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用Vue技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

Java————栈

一 、栈 Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安全的。 是一种特殊的线性表, 其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端称为栈顶,另…

【数据结构】ArrayList和顺序表

文章目录 1.线性表2.顺序表2.1 接口的实现 3. ArrayList简介4. ArrayList使用4.1 ArrayList的构造4.2 ArrayList常见操作4.3 ArrayList的遍历4.4 ArrayList的扩容机制 5. ArrayList的具体使用5.1 简单的洗牌算法5.2 杨辉三角 6. ArrayList的问题及思考 1.线性表 线性表&#x…

Angular变更检测机制

前段时间遇到这样一个 bug,通过一个 click 事件跳转到一个新页面,新页面迟迟不加载; 经过多次测试发现,将鼠标移入某个 tab ,页面就加载出来了。 举个例子,页面内容无法加载,但是将鼠标移入下图…

C语言编程题(二)运算符与位运算符优先级

#include <stdio.h>int main() { unsigned char a0xa5; unsigned char b~a>>41; printf("b%d",b); return 0;} 错误思路&#xff1a; unsigned char占一个字节&#xff0c;即8bit&#xff0c;将a写入内存中的形式为&#xff1a; 1010 0101 按照常规来…

Matlab之并行程序设计实战教程

在本教程中&#xff0c;我们将介绍如何使用Matlab进行并行程序设计。我们将通过一个简单的示例来演示如何将串行代码转换为并行代码&#xff0c;以提高程序的执行效率。 示例&#xff1a;计算一个数组的平方和 假设我们有一个包含10000个元素的数组&#xff0c;我们想计算该数…

OkHttp 根据服务器返回的的过期时间设置缓存

据返回的缓存时间来缓存响应&#xff0c;可以通过使用OkHttp的CacheControl和ResponseCacheInterceptor来实现。以下是一个示例代码&#xff1a; // 创建缓存目录和缓存对象 File cacheDirectory new File(context.getCacheDir(), "http-cache"); int cacheSize 1…

[运维|数据库] 在 PostgreSQL 中使用正则表达式进行模式匹配

以下是如何在 PostgreSQL 中使用正则表达式进行模式匹配&#xff1a; SELECT column_name FROM your_table WHERE column_name ~ your_pattern;在上面的查询中&#xff1a; column_name 是您要搜索的列名。 your_table 是包含数据的表名。 ‘your_pattern’ 是您的正则表达式…

【面试刷题】——堆栈窗口

“堆栈窗口”&#xff08;Stack Window&#xff09;通常不是一个特定的编程术语&#xff0c;但可以用来描述在编程和计算机科学领域中一些相关的概念。这些概念涉及到堆栈&#xff08;stack&#xff09;和窗口&#xff08;window&#xff09;等术语的组合。以下是一些可能涉及到…

JVM——3.StringTable字符串常量池

这篇文章我们来讲一下StringTable字符串常量池 目录 1.引例 2.StringTable的特性 3.StringTable的位置 4.StringTable的垃圾回收、 5.StringTable性能调优 6.总结 1.引例 首先&#xff0c;我们来看下面的这段程序&#xff0c;请思考最终的输出结果。 输出结果&#xff…

Multitor:一款带有负载均衡功能的多Tor实例创建工具

关于Multitor Multitor是一款带有负载均衡功能的多Tor实例创建工具&#xff0c;Multitor的主要目的是以最快的速度完成大量Tor进程的初始化&#xff0c;并将大量实例应用到我们日常使用的程序中&#xff0c;例如Web浏览器和聊天工具等等。除此之外&#xff0c;在该工具的帮助下…

常用设计模式总结 + 实例

工厂模式 工厂函数通常是指一个函数&#xff0c;它用来创建和返回其他函数或对象的实例。 人话&#xff1a; 当new Class 或 Function 时&#xff0c;根据传入的参数&#xff0c;而返回不同的值&#xff0c;这就是工厂模式。 &#xff08;所以可以说&#xff0c;这是我们开…

vscode如何设置文件折叠

随着项目的不断迭代开发&#xff0c;复杂度越来越高&#xff0c;配置文件越来越多&#xff0c;导致vscode左侧文件列表展示非常不直观&#xff0c;幸好可以通过文件折叠来简化展示效果&#xff0c;把同类相关的文件折叠在一块展示&#xff0c;方便查看配置文件。配置好后的效果…

React 开发一个移动端项目(2)

配置基础路由 目标&#xff1a;配置登录页面的路由并显示在页面中 步骤&#xff1a; 安装路由&#xff1a; yarn add react-router-dom5.3.0 5 和 6 两个版本对组件类型的兼容性和函数组件支持有所改变&#xff0c;在这里使用的是 5。 和路由的类型声明文件 yarn add types…

VTK 基础入门 ( 一 ) 相机设置

/** 相机 SetClippingRange()/SetFocalPoint() / SetPosition()分别用于设置相机的前后裁剪平面、焦点和位置。 ComputeViewPlaneNormal()方法是根据设置的相机位置、焦点等信息&#xff0c;重新计算视平面 (View Plane)的法向量。 一般该法向量与视平面是垂直…

基于 kubernetes+docker构建高可用、高性能的 web 、CICD集群

文章目录 一、项目架构图二 、项目描述三、项目环境四、环境准备1、IP地址规划2、关闭selinux和firewall3、配置静态ip地址4、修改主机名5、升级系统&#xff08;可做可不做&#xff09;6、添加hosts解析 五、项目步骤1、设计整个集群的架构&#xff0c;规划好服务器的IP地址&a…

Postgresql中检测内存越界或use after free的简便方法

1 使用场景 在Postgresql的内存管理模块中&#xff0c;最常用的aset.c提供的内存池实现&#xff0c;该实现提供了两个非常实用的开关来解决常见的内存越界问题&#xff1a; memdebug.c * About CLOBBER_FREED_MEMORY:** If this symbol is defined, all freed memory is over…

AIGC专栏6——通过阿里云与AutoDL快速拉起Stable Diffusion和EasyPhoto

AIGC专栏6——通过阿里云与AutoDL快速拉起Stable Diffusion和EasyPhoto 学习前言Aliyun DSW快速拉起&#xff08;新用户有三个月免费时间&#xff09;1、拉起DSW2、运行Notebook3、一些小bug AutoDL快速拉起1、拉起AutoDL2、运行Notebook 学习前言 快速拉起AIGC服务 对 用户体…