HQL底层原理及优化:1 干预SQL的运行方式 之1.2经过Hint对计算引擎执行过程进行干预

Hint,意为提示。web

1 Hint简介

本小节参考自文章Oracle hint详解中的一部分,感谢原做者的分享。数据库

1.1 为何引入Hint?

Hint是Oracle数据库中颇有特点的一个功能,是不少DBA优化中常常采用的一个手段。那为何Oracle会考虑引入优化器呢?基于代价的优化器是很聪明的,在绝大多数状况下它会选择正确的优化器,减轻DBA的负担。数据结构

但有时它也聪明反被聪明误选择了不好的执行计划,使某个语句的执行变得奇慢无比。此时就须要DBA进行人为的干预,告诉优化器使用指定的存取路径或链接类型生成执行计划,从而使语句高效地运行。Hint就是Oracle提供的一种机制,用来告诉优化器按照告诉它的方式生成执行计划。svg

1.2 不要过度依赖Hint

当遇到SQL执行计划很差的状况,应优先考虑统计信息等问题,而不是直接加Hint了事。若是统计信息无误,应该考虑物理结构是否合理,即没有合适的索引。只有在最后仍然不能SQL按优化的执行计划执行时,才考虑Hint。性能

毕竟使用Hint,须要应用系统修改代码,Hint只能解决一条SQL的问题,而且因为数据分布的变化或其余缘由(如索引改名)等,会致使SQL再次出现性能问题测试

1.3 Hint的弊端

Hint是比较"暴力"的一种解决方式,不是很优雅。须要开发人员手工修改代码。
Hint不会去适应新的变化。好比数据结构、数据规模发生了重大变化,但使用Hint的语句是感知变化并产生更优的执行计划。
Hint随着数据库版本的变化,可能会有一些差别、甚至废弃的状况。此时,语句自己是无感知的,必须人工测试并修正。优化

1.4 Hint与注释关系

提示是Oracle为了避免破坏和其余数据库引擎之间对SQL语句的兼容性而提供的一种扩展功能。Oracle决定把提示做为一种特殊的注释来添加。它的特殊性表如今提示必须紧跟着DELETE、INSERT、UPDATE或MERGE关键字.net

换句话说,提示不能像普通注释那样在SQL语句中随处添加。且在注释分隔符(/*)以后的第一个字符必须是加号。在后面的用法部分,会详细说明。3d

1.5 语法

  • DELETE、INSERT、SELECT和UPDATE是标识一个语句块开始的关键字,包含提示的注释只能出如今这些关键字的后面,不然提示无效。
  • "+“号表示该注释是一个提示,该加号必须当即跟在”/*"的后面,中间不能有空格。
  • hint是下面介绍的具体提示之一,若是包含多个提示,则每一个提示之间须要用一个或多个空格隔开。
  • text是其它说明hint的注释性文本

在Oracle中的Hint有许多种,Hive中的Hint还没有普遍了解,之后再补充。日志

2 使用MapJoin Hint的SQL

2.1 实现参数

MapJoin一般用于一个很小的表和一个大表进行join的场景,具体小表有多小,由参数 hive.mapjoin.smalltable.filesize来决定,该参数表示小表的总大小,默认值为25000000字节,即25M.
Hive0.7以前,须要使用hint提示* /+ mapjoin(table) */才会执行MapJoin,不然执行Common Join,但在0.7版本以后,默认自动会转换Map Join,由数hive.auto.convert.join来控制,默认为true.
仍然以9.1中的HQL来讲吧,假设a表为一张大表,b为小表,而且hive.auto.convert.join=true,那么Hive在执行时候会自动转化为MapJoin。

2.2 底层执行流程

在这里插入图片描述
如上图中的流程,首先是Task A,它是一个Local Task(在客户端本地执行的Task),负责扫描小表b的数据,将其转换成一个HashTable的数据结构,并写入本地的文件中,以后将该文件加载到DistributeCache中,该HashTable的数据结构能够抽象为:
|key| value|
| 1 | 26 |
| 2 | 34 |
在这里插入图片描述
在这里插入图片描述
图中红框圈出了执行Local Task的信息。

  • 接下来是Task B,该任务是一个没有Reduce的MR,启动MapTasks扫描大表a,在Map阶段,根据a的每一条记录去和DistributeCache中b表对应的HashTable关联,并直接输出结果。
  • 因为MapJoin没有Reduce,因此由Map直接输出结果文件,有多少个Map Task,就有多少个结果文件

2.3 测试

一、两表关联:

select e.empno,e.ename,e.deptno,d.deptno,d.dname 
from emp e join dept d 
on e.deptno = d.deptno;

条件:emp表数据为1000条,dept表数据为100条;
说明:执行时间mapjoin会经过元数据(metadata)进行查找,发现是否存在小表(根据hive.mpajoin.samlltable.filesize参数设置,判断是否为小表。此参数默认25M)。
存在小表时将先行进行小表加载到内存中,即dept表,如上HQL语句将dept表加载至内存中,最后再用emp表中数据一条一条与内存中数据进行关联查询。

二、多表关联

select e.empno,e.ename,e.deptno,d.deptno,d.dname 
from emp e join dept d join emp_partition c 
on e.deptno = d.deptno and e.empno = c.empno;

条件:emp表数据为1000条,dept表数据为100条,emp_partition表数据为500条。 说明:执行时间mapjoin会经过元数据(metadata)进行查找,发现是否存在小表(根据hive.mpajoin.samlltable.filesize参数设置,判断是否为小表。此参数默认25M)。 存在小表时将先行进行小表加载到内存中,即dept、emp_partition表,如上HQL语句将dept表加载至内存中,最后再用emp表中数据一条一条与内存中数据进行关联查询。 注:以上能够对照SQL的执行计划或执行日志更详细,后续补充相关截图及说明