查询转换(Query Transformation),又称为逻辑优化(Logical optimization),也称为软优化, 即查询转换器在逻辑上对语句做一些语义等价转换,从而能使优化器生成效率更高的执行计划。
语句在被提交到 Oracle 后,解析器(Parser)会对 SQL 语句的语法、语义分析,并将查询中的视图展开、划分为小的查询块(Query Block)。它们是嵌套或者相互关联的,而查询形式则决定了他们之间是如何关联的。这些查询块被传送给了查询转换器后,查询转换器会在不影响逻辑结果的 前提下,决定如果改变查询形式、从而改变查询块之间的关系,是否能生成更好的执行计划。
查询转换器依据特定的方式决定是否对查询块进行转换。按照其所依赖的方式部分,转换技术 可以分为两类:启发式查询转换(Heuristic Query Transformation),又称为基于规则的查询转换
(Rule Based Query Transformation);基于代价的查询转换(Cost Based Query Transformation, CBQT)
• 启发式查询转换是基于一套规则对查询进行转换,一旦满足规则所定义的条件,则对语句 进行相应的转换,部分启发式转换技术是在 RBO 时代就已经被引入了。
• 而基于代价的查询转换是否对语句进行转换则取决于语义等价语句之间的代价对比,即采
用代价最小一种。
提示:大多数基于代价的查询转换都可以从执行计划的概要数据中找到线索;而启发式查询转换则 需要从优化器跟踪(10053)信息中查找线索,并且许多跟踪记录仅能从 11g 的跟踪信息中发现。
不过,并不是每一项转换技术都被严格划分在某一类下,某些技术,例如子查询反嵌套,即包 含了启发式规则的转换,又存在基于代价的转换。
Oracle 主要采用了以下的转换技术,我们分别介绍两类转换技术,对于同时采用了两种转换规则的,我们会再做说明。
启发式查询转换
所有的启发式转换都是基于一套优化器内建的规则。在查询转换阶段,转换器会逐个针对这些 规则对查询进行检查,确定其是否满足转换规则,一旦满足,转换器就对其进行转换。
简单视图合并(Simple View Merge,SVM)
我们知道,视图(View)的实质就是一条查询语句。在解析阶段,语句中的每个视图都会被展 开至一个查询块中。如果未做视图合并,优化器则会单独分析每个视图,并为定义视图的查询语句 生成一个视图子计划。然后再分析整个查询的其他部分,并生成执行计划。在这种情况下,由于视图的执行计划和整体执行计划不是同时统一做评估的,因此其最终计划可能不是最优的执行计划。使用视图合并技术后,优化器不再单独为每个视图生成子计划,而是将视图的查询合并到整体查询中去,最终为合并和的整体查询寻找到一个最优的执行计划。要将视图查询合并到主查询中去, 优化器会将视图所依赖的表的名字替换掉视图名字、并将视图查询中的 WHERE 条件合并到主查询的 WHERE 条件中去。
根据子查询在主查询中位置以及其与主查询中所引用的表的关系的不同,子查询分为以下几种:
• 标量子查询(Scalar Subquery):出现在 SELECT 列表中的子查询被称为标量子查询;
• 内联视图(Inline View):出现在 FROM 子句中的视图被称为内联视图;
• 嵌套子查询(Nested Subquery):出现在 WHERE 子句中的子查询又被称为嵌套子查询;
• 互关联子查询(Correlated Subquery):如果嵌套子查询主查询 WHERE 条件的逻辑表达式的一部分(非 IN、EXISTS 子查询),并且嵌套子查询的查询条件中还包含主查询中表的字段,那么这样的子查询又称为互关联子查询。
提示:是否进行视图合并,可以由优化器参数_simple_view_merging 或者提示 MERGE/NO_MERGE
控制,默认为 TRUE。
视图合并又可以分为简单视图合并与复杂视图合并:
• 对于“选择-投影-关联”(Select-Project-Join)的视图的合并称为简单视图合并
(Simple View Merge),通常这种合并是属于启发式查询转换,即只要视图合并特性被开启(_simple_view_merging=TRUE)都能被合并;
• 对于含有 DISTINCT、GROUP BY 的视图的合并称为复杂视图合并(Complex View Merge) 复杂视图合并通常属于基于代价的查询转换,最终是否合并取决于代价大小,因此我
们将复杂视图合并放在下一节介绍;
当存在以下情况时,不能进行视图合并:
• 含有集合操作(UNION, UNION ALL, INTERSECT, MINUS)、聚集函数(AVG, COUNT, MAX, MIN, SUM …)、ROWNUM 和 CONNECT BY 的视图则不能被合并;
• 如果主查询语句中含有 CURSOR 表达式,则查询中的任何视图都不能被合并;
内联视图合并
我们以下面两个执行计划为例,简要说明视图合并技术对执行计划优化的影响:
示例分析:上面第一个执行计划是未使用视图合并(通过提示强制)所生成的执行计划。它为视图 V_OBJECTS 生成了一个子计划(即操作 10~12)。该计划由视图查询语句及主查询中获得的谓词条件为(“STATUS”=:C AND “OWNER”=‘SYS’ AND “OBJECT_NAME” LIKE :B),并且优化器估算出它
会返回 571 条数据记录。在这种情况下,优化器选择其与另外一个表 T_TABLES 做哈希关联,估算代价为 49;
第二个执行计划使用了视图合并技术,在选择执行计划之前,用视图的依赖表 T_OBJECTS 替换了视图 V_OBJECTS,并且将视图查询中 WHERE 条件"OWNER"='SYS’与主查询 WHERE 条件"STATUS"=:C 和关联条件"T".“TABLE_NAME”="OBJECT_NAME"合并,最终决定由这些条件访问索引T_OBJECTS_IDX1 后与表 T_TABLES 做嵌套关联,估算代价仅为 9。
基于关联的含有标量子查询的视图合并
以下是对含有标量子查询的视图与主查询中的对象进行关联操作时发生的视图合并的示例:
在上例中,含有标量子查询(SCA)的子查询(INV)与主查询合并,它们的对象可以直接关联。
含有标量子查询的简单查询视图合并
这种转换仅在 11g 及以上版本中有效。它是对对含义标量子查询的视图的简单查询进行视图合并转换:
(11.2.0.1)
在上例中,含有标量子查询(SCA)的子查询(INV)与主查询合并,视图 V 被消除。