《基于 Oracle 的 SQL 优化》笔记 第二章 Oracle 里的执行计划

如何查看执行计划的顺序

简单的原则:根据往右的缩进,最右的先执行,即从右往左;缩进相同的,从上往下执行。

Oracle 里的常见的执行计划

与表访问相关的执行计划

全表扫描对应的执行计划关键词是“TABLE ACCESS FULL”;
rowid 扫描对应的关键词是“TABLE ACCESS BY USER ROWID”(目标 SQL 直接指定了 rowid)或 “TABLE ACCESS BY INDEX ROWID”(先检索索引,然后用 rowid 访问表)。

与 B-tree 相关的执行计划

连接类型          执行计划关键词
排序合并连接        SORT JOINMERGE JOIN
嵌套循环          NESTED LOOPS
哈希连接          HASH JOIN
反连接           ANTI(可能是 HASH JOIN ANTI, MERGE JOIN ANTI, NESTED LOOPS ANTI
半连接           SEMI(可能是 HASH JOIN SEMI, MERGE JOIN SEMI, NESTED JOIN SEMI

半连接对连接结果进行必要的去重。

其他执行计划

  • AND-EQUAL(INDEX MERGE)AND-EQUAL 又称为 INDEX MERGE,是指如果 where 条件里出现了多个针对不同的单列的等值条件,并且这些列上都有单键值的索引,则 Oracle 可能会以相应的单个等值条件去分别扫描这些索引,然后 合并这些扫描单个索引所得到的 rowid 集合,如果能从这些集合中找到值系统的 rowid,那么这个 rowid 就是目标 SQL 最终执行结果所对应的 rowid。只需用这些 rowid 回表就能得到最终的结果。

INDEX JOIN:指的是针对单表上的不同索引之间的连接。如果目标 SQL 需要的数据可以从两个单键值索引里获得,Oracle 可选择扫描这两个索引得到两个结果集,然后用 rowid 相等作为连接条件连接着两个结果集,得到的就是最终结果集。INDEX JOIN 在执行计划中对应的关键字和普通的表连接一样,只不过参与连接的对象不是表而是索引。

VIEW:如果 Oracle 不能对涉及视图的查询做视图合并,那么将把该视图作为一个整体独立地执行,此时 SQL 执行计划中将出现关键字 VIEW

FILTER:是一种特殊的执行计划,对应的执行步骤有三步:1)、得到一个驱动结果集;2)、根据一定的过滤条件从上述驱动结果集中滤除不满足条件的记录;3)、结果集中剩下的记录就会返回给最终用户或者继续参与下一个执行步骤。* FILTER 类型的执行计划实际上是一种改良的嵌套循环连接,它并不像嵌套循环连接那样,驱动结果集中的记录有多少条就得访问多少次被驱动表。*

SORT

SORT 在执行计划中通常以组合的形式出现,这些组合形式包括但不限于:SORT AGGREGATE, SORT UNIQUE, SORT JOIN, SORT GROUP BY, SORT ORDER BY, BUFFER SORT。执行计划中即使出现关键字 ”sort“ 也不一定就意味着要排序,比如 SORT AGGREGATE, BUFFER SORT 就不一定需要排序。

看一个 SQL 是否排序最直观的方法就是查看其统计信息中“sorts(memory)”和“sorts(disk)”的值,如果这两个值大于 0,则说明 SQL 经历了排序。但对于 BUFFER SORT ,还要借助目标 SQL 真实执行计划中“Column Projection Information”部分 “#keys”的值来判断所对应的 SQL 到底有没有经历排序。

对于包含关键字“SORT”的执行步骤(比如:SORT ORDER BY, SORT AGGREGATE, BUFFER SORT 等),在真实执行计划中“#keys”的值表示该执行步骤实际拍序列的数量。

UNION/UNION ALL

UNION ALL 仅仅是简单地将两个结果集合并,并不做任何处理;UNION 除了将两个结果集合并之外,还会对合并后的结果集做排序和去重,相当于先做 UNION ALL,然后再对 UNION ALL 之后的结果集做 SORT UNIQUE。

CONCAT

CONCAT 就是 IN-List 扩展(IN-List Expansion)或 OR 扩展(OR Expansion),在执行计划中对应的关键词是 “CONCATENATION”。

CONNECT BY

CONNECT BY 是 Oracle 数据库中层次查询所对应关键字,在执行计划中表示同样的意思。


欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据