工作常用之Hive 调优【四】HQL 语法优化

简介: 列裁剪就是在查询时只读取需要的列,分区裁剪就是只读取需要的分区。当列很多或者数据量很大时,如果 select * 或者不指定分区,全列扫描和全表扫描效率都很低。

HQL 语法优化


3.1 列裁剪与分区裁剪


列裁剪就是在查询时只读取需要的列,分区裁剪就是只读取需要的分区。当列很多或者数据量很大时,如果 select * 或者不指定分区,全列扫描和全表扫描效率都很低。


Hive 在读数据的时候,可以只读取查询中所需要用到的列,而忽略其他的列。这样做可以节省读取开销:中间表存储开销和数据整合开销。


3.2 Group By


默认情况下, Map 阶段同一 Key 数据分发给一个 Reduce ,当一个 key 数据过大时就倾

斜了。


db772c576a344498b7b377a5a6515075.png


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


开启 Map 端聚合参数设置


1 )是否在 Map 端进行聚合,默认为 True
set hive.map.aggr = true;
2 )在 Map 端进行聚合操作的条目数目
set hive.groupby.mapaggr.checkinterval = 100000;
3 )有数据倾斜的时候进行负载均衡(默认是 false )
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 中),最后完成最终的聚合操作(虽然能解决数据倾斜,但是不能让运行速度的更快)。


hive (default)> select deptno from emp group by deptno;
Stage-Stage-1: Map: 1 Reduce: 5 Cumulative CPU: 23.68 sec HDFS Read:
19987 HDFS Write: 9 SUCCESS
Total MapReduce CPU Time Spent: 23 seconds 680 msec
OK
deptno
10
20
30


优化以后


hive (default)> set hive.groupby.skewindata = true;
hive (default)> select deptno from emp group by deptno;
Stage-Stage-1: Map: 1 Reduce: 5 Cumulative CPU: 28.53 sec HDFS Read:
18209 HDFS Write: 534 SUCCESS
Stage-Stage-2: Map: 1 Reduce: 5 Cumulative CPU: 38.32 sec HDFS Read:
15014 HDFS Write: 9 SUCCESS
Total MapReduce CPU Time Spent: 1 minutes 6 seconds 850 msec
OK
deptno
10
20
30


3.3 Vectorization


vectorization : 矢量计算的技术,在计算类似 scan, filter, aggregation 的时候,vectorization技术以设置批处理的增量大小为 1024 行单次来达到比单条记录单次获得更高的效率。


756679ec5b45447387a35e02b291ba91.png


set hive.vectorized.execution.enabled = true;
set hive.vectorized.execution.reduce.enabled = true;


3.4 多重模式


如果你碰到一堆 SQL ,并且这一堆 SQL 的模式还一样。都是从同一个表进行扫描,做不同的逻辑。有可优化的地方:如果有 n 条 SQL ,每个 SQL 执行都会扫描一次这张表。


insert .... select id,name,sex, age from student where age > 17;
insert .... select id,name,sex, age from student where age > 18;
insert .... select id,name,sex, age from student where age > 19;


-- 隐藏了一个问题:这种类型的 SQL 有多少个,那么最终。这张表就被全表扫描了多少次


insert int t_ptn partition(city=A). select id,name,sex, age from student
where city= A;
insert int t_ptn partition(city=B). select id,name,sex, age from student
where city= B;
insert int t_ptn partition(city=c). select id,name,sex, age from student
where city= c;


修改为:


from student
insert int t_ptn partition(city=A) select id,name,sex, age where city= A
insert int t_ptn partition(city=B) select id,name,sex, age where city= B


如果一个 HQL 底层要执行 10 个 Job ,那么能优化成 8 个一般来说,肯定能有所提高,多重插入就是一个非常实用的技能。一次读取,多次插入,有些场景是从一张表读取数据后,要多次利用。


3.5 in/exists 语句


在 Hive 的早期版本中, in/exists 语法是不被支持的,但是从 hive-0.8x 以后就开始支持这个语法。但是不推荐使用这个语法。虽然经过测验, Hive-2.3.6 也支持 in/exists 操作,但还是推荐使用 Hive 的一个高效替代方案: left semi join比如说: -- in / exists 实现


select a.id, a.name from a where a.id in (select b.id from b);
select a.id, a.name from a where exists (select id from b where a.id = b.id);


可以使用 join 来改写:


select a.id, a.name from a join b on a.id = b.id;


应该转换成:


-- left semi join 实现
select a.id, a.name from a left semi join b on a.id = b.id;


3.6 CBO 优化


join 的时候表的顺序的关系:前面的表都会被加载到内存中。后面的表进行磁盘扫描


select a.*, b.*, c.* from a join b on a.id = b.id join c on a.id = c.id;


Hive 自 0.14.0 开始,加入了一项 "Cost based Optimizer" 来对 HQL 执行计划进行优化,这个功能通过 "hive.cbo.enable" 来开启。在 Hive 1.1.0 之后,这个 feature 是默认开启的,它可以 自动优化 HQL 中多个 Join 的顺序,并选择合适的 Join 算法。


CBO ,成本优化器,代价最小的执行计划就是最好的执行计划。传统的数据库,成本优化器做出最优化的执行计划是依据统计信息来计算的。


Hive 的成本优化器也一样, Hive 在提供最终执行前,优化每个查询的执行逻辑和物理执行计划。这些优化工作是交给底层来完成的。根据查询成本执行进一步的优化,从而产生潜在的不同决策:如何排序连接,执行哪种类型的连接,并行度等等。


要使用基于成本的优化(也称为 CBO ),请在查询开始设置以下参数:


set hive.cbo.enable=true;
set hive.compute.query.using.stats=true;
set hive.stats.fetch.column.stats=true;
set hive.stats.fetch.partition.stats=true;


3.7 谓词下推


将 SQL 语句中的 where 谓词逻辑都尽可能提前执行,减少下游处理的数据量。对应逻辑优化器是 PredicatePushDown ,配置项为 hive.optimize.ppd ,默认为 true 。


案例实操:


1 )打开谓词下推优化属性
hive (default)> set hive.optimize.ppd = true; # 谓词下推,默认是 true
2 )查看先关联两张表,再用 where 条件过滤的执行计划
hive (default)> explain select o.id from bigtable b join bigtable o on
o.id = b.id where o.id <= 10;
3 )查看子查询后,再关联表的执行计划
hive (default)> explain select b.id from bigtable b
join (select id from bigtable where id <= 10) o on b.id = o.id;


3.8 MapJoin


MapJoin 是将 Join 双方比较小的表直接分发到各个 Map 进程的内存中,在 Map 进程中进行 Join 操 作,这样就不用进行 Reduce 步骤,从而提高了速度。如果不指定 MapJoin或者不符合 MapJoin 的条件,那么 Hive 解析器会将 Join 操作转换成 Common Join ,即:在Reduce阶段完成 Join 。容易发生数据倾斜。可以用 MapJoin 把小表全部加载到内存在 Map 端进行 Join ,避免 Reducer 处理。


1 )开启 MapJoin 参数设置


1 )设置自动选择 MapJoin


set hive.auto.convert.join=true; # 默认为 true


2 )大表小表的阈值设置(默认 25M 以下认为是小表):


set hive.mapjoin.smalltable.filesize=25000000;


2 ) MapJoin 工作机制


MapJoin 是将 Join 双方比较小的表直接分发到各个 Map 进程的内存中,在 Map 进程中进行 Join 操作,这样就不用进行 Reduce 步骤,从而提高了速度。


3 )案例实操:



1 )开启 MapJoin 功能


set hive.auto.convert.join = true; 默认为 true


2 )执行小表 JOIN 大表语句


注意:此时小表 ( 左连接 ) 作为主表,所有数据都要写出去,因此此时会走 reduce , mapjoin失效


Explain insert overwrite table jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from smalltable s
left join bigtable b
on s.id = b.id;
Time taken: 24.594 seconds


3 )执行大表 JOIN 小表语句


Explain insert overwrite table jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable b
left join smalltable s
on s.id = b.id;


Time taken: 24.315 seconds


3.9 大表、大表 SMB Join (重点)


SMB Join : Sort Merge Bucket Join


1 )创建第二张大表


create table bigtable2(
id bigint,
t bigint,
uid string,
keyword string,
url_rank int,
click_num int,
click_url string)
row format delimited fields terminated by '\t';
load data local inpath '/opt/module/data/bigtable' into table bigtable2;


2 )测试大表直接 JOIN


insert overwrite table jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable a
join bigtable2 b
on a.id = b.id;


测试结果: Time taken: 72.289 seconds


insert overwrite table jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable a
join bigtable2 b
on a.id = b.id;


3 )创建分通表 1


create table bigtable_buck1(
id bigint,
t bigint,
uid string,
keyword string,
url_rank int,
click_num int,
click_url string)
clustered by(id)
sorted by(id)
into 6 buckets
row format delimited fields terminated by '\t';
load data local inpath '/opt/module/data/bigtable' into table
bigtable_buck1;


4 )创建分通表 2 ,分桶数和第一张表的分桶数为倍数关系


create table bigtable_buck2(
id bigint,
t bigint,
uid string,
keyword string,
url_rank int,
click_num int,
click_url string)
clustered by(id)
sorted by(id)
into 6 buckets
row format delimited fields terminated by '\t';
load data local inpath '/opt/module/data/bigtable' into table
bigtable_buck2;


5 )设置参数


set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
set
hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;


6 )测试 Time taken: 34.685 seconds


insert overwrite table jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable_buck1 s
join bigtable_buck2 b
on b.id = s.id;


3.10 笛卡尔积


Join 的时候不加 on 条件,或者无效的 on 条件,因为找不到 Join key , Hive 只能使用 1个 Reducer 来完成笛卡尔积。当 Hive 设定为严格模式( hive.mapred.mode=strict , nonstrict )时,不允许在 HQL 语句中出现笛卡尔积。

目录
相关文章
|
7月前
|
SQL 存储 分布式计算
Hive数据仓库设计与优化策略:面试经验与必备知识点解析
本文深入探讨了Hive数据仓库设计原则(分区、分桶、存储格式选择)与优化策略(SQL优化、内置优化器、统计信息、配置参数调整),并分享了面试经验及常见问题,如Hive与RDBMS的区别、实际项目应用和与其他组件的集成。通过代码样例,帮助读者掌握Hive核心技术,为面试做好充分准备。
660 0
|
2月前
|
SQL 分布式计算 关系型数据库
Hadoop-13-Hive 启动Hive 修改启动参数命令行启动测试 几句简单的HQL了解Hive
Hadoop-13-Hive 启动Hive 修改启动参数命令行启动测试 几句简单的HQL了解Hive
71 2
|
2月前
|
SQL 分布式计算 Hadoop
Hadoop-14-Hive HQL学习与测试 表连接查询 HDFS数据导入导出等操作 逻辑运算 函数查询 全表查询 WHERE GROUP BY ORDER BY(一)
Hadoop-14-Hive HQL学习与测试 表连接查询 HDFS数据导入导出等操作 逻辑运算 函数查询 全表查询 WHERE GROUP BY ORDER BY(一)
56 4
|
2月前
|
SQL 分布式计算 Hadoop
Hadoop-12-Hive 基本介绍 下载安装配置 MariaDB安装 3台云服务Hadoop集群 架构图 对比SQL HQL
Hadoop-12-Hive 基本介绍 下载安装配置 MariaDB安装 3台云服务Hadoop集群 架构图 对比SQL HQL
85 3
|
2月前
|
SQL
Hadoop-14-Hive HQL学习与测试 表连接查询 HDFS数据导入导出等操作 逻辑运算 函数查询 全表查询 WHERE GROUP BY ORDER BY(二)
Hadoop-14-Hive HQL学习与测试 表连接查询 HDFS数据导入导出等操作 逻辑运算 函数查询 全表查询 WHERE GROUP BY ORDER BY(二)
43 2
|
3月前
|
SQL 数据处理 HIVE
HIVE的数据倾斜调优
hive数据倾斜主要是由shuffle引起的,而引起shuffle的又主要有四种情况,分别为: 1.group by 2.join 3.count(distinct) 4.开窗函数
75 8
|
5月前
|
SQL 分布式计算 关系型数据库
Hadoop-12-Hive 基本介绍 下载安装配置 MariaDB安装 3台云服务Hadoop集群 架构图 对比SQL HQL
Hadoop-12-Hive 基本介绍 下载安装配置 MariaDB安装 3台云服务Hadoop集群 架构图 对比SQL HQL
79 2
|
7月前
|
SQL 分布式计算 资源调度
Hive 优化总结
Hive优化主要涉及HDFS和MapReduce的使用。问题包括数据倾斜、操作过多和不当使用。识别倾斜可通过检查分区文件大小或执行聚合抽样。解决方案包括整体优化模型设计,如星型、雪花模型,合理分区和分桶,以及压缩。内存管理需调整mapred和yarn参数。倾斜数据处理通过选择均衡连接键、使用map join和combiner。控制Mapper和Reducer数量以避免小文件和资源浪费。减少数据规模可调整存储格式和压缩,动态或静态分区管理,以及优化CBO和执行引擎设置。其他策略包括JVM重用、本地化运算和LLAP缓存。
172 4
Hive 优化总结
|
6月前
|
SQL 资源调度 数据库连接
Hive怎么调整优化Tez引擎的查询?在Tez上优化Hive查询的指南
在Tez上优化Hive查询,包括配置参数调整、理解并行化机制以及容器管理。关键步骤包括YARN调度器配置、安全阀设置、识别性能瓶颈(如mapper/reducer任务和连接操作),理解Tez如何动态调整mapper和reducer数量。例如,`tez.grouping.max-size` 影响mapper数量,`hive.exec.reducers.bytes.per.reducer` 控制reducer数量。调整并发和容器复用参数如`hive.server2.tez.sessions.per.default.queue` 和 `tez.am.container.reuse.enabled`
552 0
|
7月前
|
SQL 存储 大数据
Hive的查询、数据加载和交换、聚合、排序、优化
Hive的查询、数据加载和交换、聚合、排序、优化
153 2