在Oracle中,经常使用Hint有哪些?程序员
Oracle的Hint是用来提示Oracle的优化器,用来选择用户指望的执行计划。在许多状况下,Oracle默认的执行方式并不老是最优的,只不过因为平时操做的数据量比较小,因此,好的执行计划与差的执行计划所消耗的时间差别不大,用户感受不到而已。但对于书写操做大数据量的SQL而言,其SQL的书写则须要先了解一下执行计划是否最优或知足生产须要。一般当从开发环境迁移到生产环境下时,每每会出现此类状况。面试
例如:假设有一张客户表,在客户类别上有索引。若是想查找某一类别用户,而该类别用户占总数的比例高达90%,那么此时采用全表扫描方式将会比索引扫描方式快。若是不使用Hint,那么Oracle极可能会选择使用索引方式来执行。sql
使用Hint能够实现如下功能:数据库
(1)改变SQL中的表的关联顺序。微信
(2)改变SQL中的表的关联方式。网络
(3)实现并行方式执行DML、DDL以及SELECT语句。app
(4)改变表的访问路径(数据读取方式)。ide
(5)调整查询转换类型,重写SQL。学习
(6)调整优化器优化目标。大数据
(7)调整优化器类型。
Oracle推出了一个隐含参数“_OPTIMIZER_IGNORE_HINTS”,取值为TRUE或FALSE,缺省值是FALSE。Oracle能够经过将该隐含参数设置为TRUE,使得Oracle优化器忽略语句中全部的Hint。显然,Oracle提供此参数的目的就是在不修改应用的前提下,忽略全部Hint,让Oracle优化器本身来选择执行路径。
Hint的语法格式以下所示:
1{SELECT | INSERT | UPDATE | DELETE | MERGE} /*+ <具体的Hint内容>*/
2
关于Hint须要注意如下几点:
l Hint中第一个星号(*)和加号(+)之间不能有空格。
l Hint中加号(+)和具体的Hint内容之间能够有空格,也能够没有空格,但一般为了规范和区别于注释建议加上空格。
l Hint中的具体内容能够是单个Hint,也能够是多个Hint的组合,若是是后者,那么各个Hint间至少须要用1个空格来彼此分隔。
l Hint必须紧随关键字SELECT、INSERT、UPDATE、DELETE或MERGE以后。
l 若是在目标SQL中使用了Hint,那么就意味着自动启用了CBO,即Oracle会以CBO来解析含Hint的目标SQL。可是对于RULE和DRIVING_SITE来讲,它们能够在RBO下使用,并且不自动启用CBO。
l Hint中指定具体对象时(好比指定表名或索引名),不能带上该对象所在SCHEMA的名称,即便该SQL文本中己经有对应的SCHEMA名称。
l Hint中指定具体表名时,若是该表在对应SQL文本中有别名,那么在Hint中应该使用该表的别名。
l 对于简单的SQL语句通常只有一个查询块(Query Block),那么在其上设置Hint其做用范围就是该语句块,而对于复杂的有多个查询语句的SQL语句(例如查询中用到了子查询、内联视图、集合等操做时),各个Hint的做用域是不一样的。Hint生效的范围仅限于它自己所在的查询块,若是在Hint中不指定该Hint生效的查询块,那么Oracle会默认认为它生效的范围是指该Hint所处于的查询块。
l 因为各类缘由致使Hint被Oracle忽略后,Oracle并不会给出任何提示或者警告,更不会报错,目标SQL依然能够正常执行。致使Hint失效的缘由一般有:
① 使用的Hint有语法或者拼写错误。
② 使用的Hint是无效的(例如,在非等值链接中使用了USE_HASH)。
③ 使用的Hint是自相矛盾的(例如,即指定了FULL又指定了INDEX_FFS),但Oracle只是将自相矛盾的Hint所有忽略掉,而组合Hint中的其它Hint依然有效。
④ 使用的Hint受到了查询转换的干扰。
⑤ 依据Hint执行的结果是错误的(例如在非空的索引列上计算行数)。
⑥ 使用的Hint受到了保留关键字的干扰。Oracle在解析Hint的时候,从左到右进行,若是遇到一个词是Oracle关键字或保留字,那么Oracle将忽略这个词以及以后的全部词。若是遇到的一个词既不是关键字也不是Hint,那么就忽略该词。若是遇到的词是有效的Hint,那么就会保留该Hint。Oracle的保留字或者关键字能够经过视图V$RESERVED_WORDS来查询。由此能够知道下面5条SQL语句中只有1和4中的APPEND提示是起做用的。
11. INSERT /*+ APPEND,PARALLEL(T1) */ INTO T1 SELECT * FROM T2;
22. INSERT /*+ PARALLEL(T1), APPEND */ INTO T1 SELECT * FROM T2;
33. INSERT /*+ THIS IS APPEND */ INTO T1 SELECT * FROM T2;
44. INSERT /*+ THIS APPEND */ INTO T1 SELECT * FROM T2;
55. INSERT /*+ NOLOGGING APPEND */ INTO T1 SELECT * FROM T2;
由于“IS”是一个关键字,“,”(逗号)也是一个关键字,因此,上面的第2和第3条SQL,Oracle解析时,当遇到“,”和“IS”时,就忽略了后面的全部Hint。在第4条SQL中,THIS并非一个关键字,因此,APPEND提示有效。为了不这样的状况发生,当在SQL中书写Hint时,在/*+ */这种结构内只写Hint,而不要写逗号,或者是其它的注释。若是要对SQL写注释,那么能够在专门的注释结构中书写。
在SQL语句优化过程当中,常常会用到Hint,经过在SQL语句中设置Hint从而影响SQL的执行计划,经过V$SQL_HINT视图能够查询全部的Hint,下表是一些经常使用的Hint:
表 3-19 经常使用Hint介绍
建议对上表中每一个Hint都作相关的实验来深刻学习,而本书再也不详述。最后须要说明一下有关NOLOGGING的错误使用状况。下面几条SQL都是使用NOLOGGING时的错误用法:
1INSERT INTO T1 NOLOGGING;
2INSERT INTO T1 SELECT * FROM T2 NOLOGGING;
3INSERT /*+ NOLOGGING */ INTO T1 VALUES ('0');
4INSERT /*+ NOLOGGING */ INTO T1 SELECT * FROM T2;
5DELETE /*+ NOLOGGING */ FROM T1;
6UPDATE /*+ NOLOGGING */ T1 SET A='1';
实际上,上述全部的SQL没有一个可以实现“不产生”日志的数据更改操做。事实上,NOLOGGING并非Oracle的一个有效的Hint,而是一个SQL关键字,一般用于DDL语句中。这里NOLOGGING至关于给SELECT的表指定了一个别名为“NOLOGGING”。下面是NOLOGGING的一些正确用法:
1CREATE TABLE T1 NOLOGGING AS SELECT * FROM T2;
2CREATE INDEX T1_IDX ON T1(A) NOLOGGING;
3ALTER INDEX T1_IDX REDUILD ONLINE NOLOGGING;
4ALTER TABLE T1 NOLOGGING;
若面试官问如何强制一个SQL语句使用索引,此时就能够回答使用Hint,/*+INDEX(TABLE INDEX_NAME)*/来完成。
& 说明:
有关Hint的更多内容能够参考个人BLOG:http://blog.itpub.net/26736162/viewspace-2125011/、http://blog.itpub.net/26736162/viewspace-2125709/
本文选自《Oracle程序员面试笔试宝典》,做者:李华荣。
详细内容能够添加麦老师微信或QQ私聊。
● 本文做者:小麦苗,只专一于数据库的技术,更注重技术的运用
● 做者博客地址:http://blog.itpub.net/26736162/abstract/1/
● 本系列题目来源于做者的学习笔记,部分整理自网络,如有侵权或不当之处还请谅解
● 版权全部,欢迎分享本文,转载请保留出处
● QQ:646634621 QQ群:618766405
● 提供OCP、OCM和高可用部分最实用的技能培训
● 题目解答如有不当之处,还望各位朋友批评指正,共同进步
长按下图识别二维码或微信扫描下图二维码来关注小麦苗的微信公众号:xiaomaimiaolhr,学习最实用的数据库技术。
本文分享自微信公众号 - DB宝(lhrdba)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。