LEADING提示的作用和使用方法
LEADING提示是指导优化器,尽量先访问指定的表或表的集合。该提示相较于ORDERED提示更灵活。
LEADING提示的使用语法如下图所示:
其中:
tablespec表示目标表的名称或别名(当有别名时,必须用别名)。但不要加入表的属主(SCHEMA)名,哪怕在SQL中,明确写了属主,提示中也不能写。
queryblock表示查询块。优化器在为一条SQL制定执行计划时,会将该SQL中涉及的子查询和视图,拆分为相应的查询块。分别为每一个查询块制定执计划。
下面,我们通过实验来说明施加该提示时,优化器是如何选择表的访问次序的。
测试验证
首先,我们创建两个测试表TAB1、TAB2:
并在其上收集统计信息,如下图所示:
然后我们在其这两个表上执行如下的查询:
select count(*)
from tab1,tab2
where tab1.object_id=tab2.object_id;
当我们什么提示都不加时,其执行计划如下:
如上图所示,此时是先访问TAB1表,然后才是TAB2表。
下面,我们使用LEADING提示,让优化器考虑先访问TAB2表。如下图所示:
但是,当我们提供了多个LEADING提示时,优化器会忽略所有的LEADING提示。如下图所示:
如上所示,并不是如提示中所期望的,先访问TAB2表,再访问TAB1表。那是否可能是优化器在处理提示时,是从后往前处理,即,先处理leading(tab1),再处理leading(tab2)。如果是这样的话,那么上面的执行计划,就是预期的执行计划。
为了验证这一点,我们交换两个LEADING的次序,让LEADING(TAB1)在前,LEADING(TAB2)在后,如果猜测成立,那么应该是先访问TAB2,再访问TAB1。测试结果如下:
如上所示,证明我们的猜测是不成立的。实际上,这是由于两个leading提示发生了冲突,一个让优化器把TAB1做为驱动表,而另一个让优化器把TAB2做为驱动表,这显然是矛盾的。
同理,LEADING提示与ORDERED提示一同使用时,也会导致LEADING提示被忽略。即可以理解为,ORDERED提示的优先级高于LEADING提示。测试过程如下:
如上所示,我们可以看到并不是先访问的TAB2表。
当我们需要指定多张表优先访问时,需要在一个LEADING提示中进行指定。如下所示:
如上所示,我们在LEADING提示中,指定按先访问TAB3表,再访问TAB2表的次序进行。(注:上面的TAB3表的创建方法与TAB1和TAB2表的创建方法类似,故这里不再赘述。),但我们从执行计划中,虽然看到的是先访问了TAB1表,然后才是访问TAB3和TAB2表,只是在访问TAB3和TAB2表时,先访问的是TAB3,后访问的是TAB2。那是不是我们把TAB1也加到LEADING提示中,并且放到最后,就能走出先访问TAB3,再访问TAB2,最后访问TAB1的结果呢?测试结果如下:
如上图所示,我们可以看到并没有如我们预期那样,TAB1表放到最后访问。所以,从这里,我们也要注意到,提示(HINT)并不是强制的行为,优化器有时,并不一定会按照提示中期望的那样行事。有时,还需要配合一些其它提示,来完成预期的行为。比如上例,我们需要再添加一个 no_swap_join_inputs(tab1)的示,才可以实现我们预期的行为,如下图所示:
知识总结
1、LEADING提示是指导优化器,按照指定的次序来访问表。
2、当需要指定多张表时,需要写在一个LEADING提示中,不要写多个LEADING提示。写多个LEADING提示,会导致全部的LEADING提示被忽略。
3、LEADING提示的优化级低于ORDERED提示,当两个提示出现时,LEADING提示会被忽略。