这两天在准备写一个关于降低buffer gets进行sql优化的文章时,无意中发现一篇熊军老师2012年写的文章:《Oracle Index Internals》,就先学习了一下。文章对B-Tree索引进行了深入的阐述,我上一篇的is null使用联合索引的案例,这篇文章也提到了。更巧的是,本文下面的内容,也与文章的的这一页有关:
这些描述都是比较准确的,大家如果有兴趣都可以自己动手操作一下,相信都会得到同样的结论。对于其中全表扫描的4次逻辑读,好像只有在建表时同时插入记录的情况才会只有4次逻辑读,如果是先建空表,再插入记录,此时的全表扫描最少要7~8个逻辑读了,这个问题老虎刘还没有深入研究(只是简单做了一些dump block的对比,没发现真相),如果有哪位大师搞清楚了,可以让老虎刘学习一下。
上面文章中的数据已经说明了一个问题,就是:小表也需要建索引。
今天我们主要研究最后一种情况,也就是2个逻辑读的情况,有没有办法让它再减少一个逻辑读?
先来看某客户一个大型系统awr TOP CPU的top 6 SQL(top1在上上篇文章中提到过):
SQL代码:
select free_minus_name, free_type
from table_conf
where free_code = :FREE_CODE;
table_conf(化名)是一个只有80几条记录的小表,free_code字段上有单字段unique索引。这个sql的平均buffer gets就是2(在awr的top gets部分有显示)。
一般来说这种sql没人再去优化了,但是这个sql执行次数多,如果能把buffer gets降低1个,基本上对CPU的消耗也会降低一半,在这里还是值得研究一下的。经过一些分析和测试,老虎刘给出的方法是:
1、创建free_code+free_minus_name+free_type 3字段联合索引(注意:free_code一定要在第一位,是否unique index没关系);
2、在where 条件中增加rownum=1(SQL逻辑没有变)
经过上面优化后可以从2 buffer gets 降到1buffer gets。
如果你的SQL执行次数不多,你就没必要做这个优化了。当然,优化方法还是值得参考的。有时候,小表与大表关联,如果执行次数多,也可以使用这个方法。
总结:
小表也需要索引;
小表的索引,经过上面的优化后,能减少一个buffer gets。
你们发现没有,包括这篇文章在内,老虎刘有很多SQL优化都用到了rownum,相信能对大家有所帮助。
本文分享自 老虎刘谈oracle性能优化 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!