Oracle 执行计划总结
方式:
sql前面加explain plan for
pl/dv工具快捷方式:f5按键;
举例:
description:执行描述
Obj own:项目拥有者
Obj name:项目名
cost:Oracle算法算出的值,越高代表性能越差,消耗越长
cardinality:扫描行数,Oracle预估的执行该sql会扫描的数据行数,注意是预估行数不是精准行数
bytes:扫描数据量大小
关注执行计划的目的:
检查sql执行过程,数据扫描方式,表连接方式,消耗资源值,以此来定位sql执行过慢出现的异常点
执行计划主要操作目的:
想办法优化sql降低cost值,cost是Oracle通过算法计算出的预估执行sql所需消耗的资源,cost越高,占用资源越大,执行效率也越慢
优化cost值方式:
通过分析description来分析异常点和优化异常点
description:
description中主要包含信息:
1、表关联方式
2、数据扫描方式
表关联方式一般常见的是两种:
1、嵌套循环(NESTED LOOPS)
2、哈希连接(HASH JOIN)
3、排序-合并连接(SORT MERGE JOIN)
由于合并连接不常见,这里不做讨论,那么表关联方式中,nested和hash到底使用哪一个比较好?
答:关联方式没有哪一种绝对的好,根据实际情况优化关联方式才是最正确的选择;
nested最适用也是最简单的连接方式。类似于用两层循环处理两个游标,外层游标称作驱动表,Oracle检索驱动表的数据,一条一条的代入内层游标,查找满足WHERE条件的所有数据,因此内层游标表中可用索引的选择性越好,嵌套循环连接的性能就越高。
hash先将驱动表的数据按照条件字段以散列的方式放入内存,然后在内存中匹配满足条件的行。哈希连接需要有合适的内存,而且必须在CBO优化模式下,连接两表的WHERE条件有等号的情况下才可以使用。哈希连接在表的数据量较大,表中没有合适的索引可用时比嵌套循环的效率要高;
简单经验总结,完全走索引,nested会比hash好;数据量很大的表中hash回避nested好些;
数据扫描方式,常见如下:
1、index unique scan 主键扫描
2、index range scan 索引范围扫描
3、index skip scan 索引跳跃扫描
4、index fast full scan 索引快速全扫
5、index full scan 索引全扫
6、table access full 全表扫描
性能从快到慢,遇到全扫,肯定要想办法优化;
重要点(敲小黑板):
当然,全扫不是一定就慢,即使数据量很大的表;
如果开了并行,注意;开了并行;大多数都会走上全扫,这时候不一定说全扫就很慢了,关注description关注的目的是为了降低cost,开了并行cost不高的情况下全扫性能也会比较快;
那么优化sql主要优化啥?
第一步主要优化的是扫描方式,选择是否走索引,是否开启并行等,
第二部就是选择join的连接方式了,是left还是inner等等,根据实际情况选择连接方式
观察执行计划图:
sql执行步骤,第一步sql会在第一个树形结构最小点进行开始,我这个开了并行是full全扫;
接下来会跳转到第一个join节点,走hash或者走nested这里就能看出,在第二个叶子执行出可以看出扫面关联表的方式;
走完第二个分支叶子后,走到第二个叶子的关联节点处,同时会跳往第三个叶子,同时会展示出相关关联方式,同样第三个叶子处也能看到数据扫描该表的方式;
同理n个关联就能看到n个关联方式和该关联表的扫描方式;
所以总结下:
看执行计划:
目标:降低cost,提高性能
方式:关注description执行描述,
通过具体问题可以选择不同方式,例如:
1、添加索引
2、优化关联方式
3、开启并行
4、添加更多where条件缩小数据集范围等等
最后,说一下并行,并行是不是一定开了最好?
答:不一定,因为开了并行,大多数会走全扫,这时候如果sql本身是走高性能索引的情况下开并行,反而会影响sql的执行效率;在走全扫的情况下开启并行能提高sql执行效率,所以建议在开启并行前先看看开与不开的执行计划再决定是否要开启并行;