1.查询转换的作用
oracle里的查询转换(Query Transformation),又称查询改写(Query Rewrite),它是oracle在解析目标sql的过程中的重要一步,是指oracle在解析目标sql时可能会对其做等价改写,目的是为了能更高效的执行目标sql,即oracle可能会将目标sql改写成语义上完全等下但执行效率更高的形式。
下图为查询转换在解析的位置
2.子查询展开
2.1.what
在查询转换步骤把带子查询的sql中的子查询不作为一个独立的处理单元来单独执行,而是将该子查询转换为它自身和外部查询之间等价的表连接。
这种等价表连接转换要么是把子查询拆开,要么是不拆开但是会把该子查询转换为一个内嵌试图(Inline View),然后再和外部查询中的表、视图做表连接。
当然了,对于不能展开的子查询是不会展开的,还是作为一个独立的单元执行。
oracle10g以及以后的版本中,对于那种不拆开子查询但是会把该子查询转换成一个内嵌试图的子查询展开,只有当经过子查询展开后等等价改写sql的成本值小于原sql的成本值时,oracle才不会对原sql执行子查询展开。
2.2.目的
子查询展开通常都是为了提高原sql 的执行效率,因为如果原sql不做子查询展开,那么通常情况下该子查询就会在其执行计划的最后一步才被执行,并且会走FILTER类型的执行计划。
3.使用条件
oracle数据库里子查询前的where条件如果是如下这些条件之一,那么这种类型的目标sql在满足了一定的条件后就可以做子查询展开。
single-row(即=,<,>,<=,>=和<>)
exists
not exists
in
not in
any
all
4.示例(sh用户)
/*+ no_unnest */ 作用是使优化器不对该sql做子查询展开
SQL> set autotrace traceonly
SQL> set timing on
select t1.cust_last_name,t1.cust_id from customers t1 where t1.cust_id in (select /*+ no_unnest */ t2.cust_id from sales t2 where t2.amount_sold >700);
对比
select t1.cust_last_name,t1.cust_id from customers t1 where t1.cust_id in (select t2.cust_id from sales t2 where t2.amount_sold >700);
我们发现,做了子查询展开的效率明显提高,因为如果不做子查询展开,子查询通常都会放在最后被执行。
3.视图合并
视图合并跟子查询展开类似,就是说对于sql语句中有视图的sql,把视图对应的基表跟其他表进行查询,而不会出现视图。合并的过程会保证语义的相同,当然了,并不是所有的视图都可以被合并。
需要注意的是执行计划中出现view并不一定是没有做视图合并,可能是临时视图等。
后续关于oracle 里的查询转换还有很多,但是自己看了一下太多,暂时略过。