Hint,意为提示。web
本小节参考自文章Oracle hint详解中的一部分,感谢原做者的分享。数据库
Hint是Oracle数据库中颇有特点的一个功能,是不少DBA优化中常常采用的一个手段。那为何Oracle会考虑引入优化器呢?基于代价的优化器是很聪明的,在绝大多数状况下它会选择正确的优化器,减轻DBA的负担。数据结构
但有时它也聪明反被聪明误,选择了不好的执行计划,使某个语句的执行变得奇慢无比。此时就须要DBA进行人为的干预,告诉优化器使用指定的存取路径或链接类型生成执行计划,从而使语句高效地运行。Hint就是Oracle提供的一种机制,用来告诉优化器按照告诉它的方式生成执行计划。svg
当遇到SQL执行计划很差的状况,应优先考虑统计信息等问题,而不是直接加Hint了事。若是统计信息无误,应该考虑物理结构是否合理,即没有合适的索引。只有在最后仍然不能SQL按优化的执行计划执行时,才考虑Hint。性能
毕竟使用Hint,须要应用系统修改代码,Hint只能解决一条SQL的问题,而且因为数据分布的变化或其余缘由(如索引改名)等,会致使SQL再次出现性能问题。测试
Hint是比较"暴力"的一种解决方式,不是很优雅。须要开发人员手工修改代码。
Hint不会去适应新的变化。好比数据结构、数据规模发生了重大变化,但使用Hint的语句是感知变化并产生更优的执行计划。
Hint随着数据库版本的变化,可能会有一些差别、甚至废弃的状况。此时,语句自己是无感知的,必须人工测试并修正。优化
提示是Oracle为了避免破坏和其余数据库引擎之间对SQL语句的兼容性而提供的一种扩展功能。Oracle决定把提示做为一种特殊的注释来添加。它的特殊性表如今提示必须紧跟着DELETE、INSERT、UPDATE或MERGE关键字。.net
换句话说,提示不能像普通注释那样在SQL语句中随处添加。且在注释分隔符(/*)以后的第一个字符必须是加号。在后面的用法部分,会详细说明。3d
在Oracle中的Hint有许多种,Hive中的Hint还没有普遍了解,之后再补充。
日志
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。
如上图中的流程,首先是Task A,它是一个Local Task(在客户端本地执行的Task),负责扫描小表b的数据,将其转换成一个HashTable的数据结构,并写入本地的文件中,以后将该文件加载到DistributeCache中,该HashTable的数据结构能够抽象为:
|key| value|
| 1 | 26 |
| 2 | 34 |
图中红框圈出了执行Local Task的信息。
一、两表关联:
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的执行计划或执行日志更详细,后续补充相关截图及说明