USE_CONCAT提示的作用和使用方法
USE_CONCAT提示是指导优化器,在处理where子句中的OR条件时,将每一个OR条件都拆成只包含OR条件中的其中一个的子句,然后将这些子句用UNION ALL联接起来,并去除那些在其它子句中已经出现的记录。
USE_CONCAT提示的使用语法如下图所示:
其中:
tablespec表示目标表的名称或别名(当有别名时,必须用别名)。但不要加入表的属主(SCHEMA)名,哪怕在SQL中,明确写了属主,提示中也不能写。
queryblock表示查询块。优化器在为一条SQL制定执行计划时,会将该SQL中涉及的子查询和视图,拆分为相应的查询块。分别为每一个查询块制定执计划。
其使用方法和注意事项,也与INDEX提示相同,为节省篇幅,这再不再赘述。
下面,我们通过实验来说明施加该提示时,优化器是如何拆分子句的。
测试验证
首先,我们创建测试表TESTTAB,并收集统计信息:
然后,我们在owner列和object_type列上分别创建两个索引,如下图所示:
设置SQLPLUS下的环境参数,以便显示的内容方便查看。如下图所示:
发出以下查询:
select * FROM testtab
where owner like 'S%'
or object_type like 'T%';
在该查询的WHERE子句中,存在一个OR条件,当我们什么提示都不加时,Oracle优化器给出的执行计划如下所示:
如上图所示,我们可以看到执行计划中,使用的全表扫,且只有一次,并没有拆成两段。
而当我们添加use_concat提示后,如下所示:
select /*+ use_concat */ * FROM testtab
where owner like 'S%'
or object_type like 'T%';
其执行计划如下图所示:
如上图所示,我们可以看到该执行计划中,对TESTTAB表访问了两次。再结合下在的谓词信息,我们可以看到这两次分别是对owner like 'S%'和object_type like 'T%'做的处理。
但是,有一点需要注意,如果OR条件所在列上无索引,则use_concat的提示会被忽略,即不会做or条件拆分。我们来验证一下:
将其中一个索引删除,比如我们删除object_type列上的索引,如下图所示:
这时,我们再执行上面的带有use_concat提示的SQL,看看此时的执行计划:
如上图所示,可以看到并没有拆分。
而且,WHERE子句中,除了OR条件外,还有其它逻辑操作符(比如AND),也是不影响的。比如下面的SQL:
select /*+ use_concat */ * FROM testtab
where (owner like 'S%' or object_type like 'T%')
and object_name='ABC';
我们先将前边删除的索引恢复,如下图所示:
此时再次执行带有use_concat和AND条件的SQL,其执行计划如下:
知识总结
1、USE_CONCAT提示是指导优化器,在处理where子句中的OR条件时,将每一个OR条件都拆成只包含OR条件中的其中一个的子句,然后将这些子句用UNION ALL联接起来,并去除那些在其它子句中已经出现的记录。
2、在OR条件列有存在索引,是该提示可以生效的前提条件。
参考文档
《Oracle® Database SQL Language Reference》