目录:
配套视频课程
SQL优化简介
一般在应用中,
糟糕的SQL语句是造成系统性能低下的最主要原因,例如大小写的不统一、同样的SQL语句不同的写法等。而且,随着数据量的增加,情况会变得越来越严重。(题外话:优秀的Oracle数据库优化人才,是任何公司都稀缺的)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
SQL调节的目标
SQL调节包括三大目标:降低负载、均衡负载和并行化负载。
l降低负载:即寻找更高效的途径来完成相同的功能
如某个非大表(小于2000万行数据数据或小于2G大小的单表),常规查询需要访问的数据实践中90%情况下是不会超过20%的,此时建立合理的索引是有效的方法之一
l均衡负载:即应该把任务分时段均衡调度
如一般系统白天是访问高峰,如果此时备份任务、批处理任务或报表数据抽取任务也
挤在这个时段则易造成负载峰值现象,正确的做法应该是把备份任务、批处理任务和报表数据抽取任务放到晚上进行处理,或采用并行化策略
l并行化负载:即大数据量的查询访问需要使用并发策略
如在数据仓库环境中应该多使用并发策略,此举可以明显减少响应时间
SQL优化阶段
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
使用OEM发现顶级SQL
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
在OEM中,选择性能->其它监视链接->定级活动,如下图:
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
不要用*代替所有列名
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
指定仅仅需要的列名与使用*对比:
时间:359/1327=27.05% CUP耗费:
4092121327/6413227637=63.81%
IO耗费: 29601/110117=26.88%
可见大幅降低I/O从而降低响应时间!
SQL优化技巧
使用TRUNCATE代替DELETE
默认PCTFREE为10,假定为5,high-water mark是一个存储段分配多少存储器的标记。
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
活用COMMIT
lUNDO段上用于恢复数据的信息
l事物中DML语句获得的锁
lSGA中重做日志缓冲区中的空间
lOracle为管理相关资源(如上述资源) 而开销的内部资源
体验例子流程如下 :
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
体验例子显示 :
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
减少表的查询次数
1.一个逻辑单元中,将能读出的列一次性读出,且尽量存放在本地变量中,应该杜绝不要用一个读一个
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
2.在包含子查询的SQL中,要特别注意减少对表的查询次数,在代码清晰时对于能减少查询次数的应坚决减少,举例如下:
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
2.执行计划如下,结论是什么?
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
以EXISTS代替DISTINCT
多表信息的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXISTS替换, EXISTS
使查询更为迅速,因为此时RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果。
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
优化前:
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
优化后:
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
使用默认值
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
使用默认之后的执行时间比为1.063/2.657=40.01%,快了一倍多!
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
可见在不含默认值,是null的列上没有使用索引,是全表扫描!而使用了默认值的列上使用了索引范围扫描!
l不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能
l任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的
l如果每列确实可能存在空值的情况,可以使用默认值的方式替代以便充分利用索引提高性能
使用DECODE函数减少处理步骤
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
l使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.
lDECODE函数也可以运用于GROUP BY 和ORDER BY子句中.
l上述例子有两步相似的操作,使用DECODE后节省一半时间,如果一组相似的操作越多,节省的时间则越多,计算公式为n-1,其中n为相似操作的步骤数
通配符的使用技巧
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
上例中已知数据%DX_ACCOUNT_TRADE%,只有以I开头的
首位使用通配符是首位不使用通配符执行效率的:0.031/1.891=1.639%
l当通配符出现在LIKE后面字符串的首位时,索引将不会被使用,因此在已知某字符的情况下,LIKE查询中应尽量不要把通配符写在首位
l%代表不定长的字符,_代表定长的字符,如果在确定要通配的字符长度时,应该尽量使用_,而不是%
定义并执行严格的SQL编写规范
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
使用Oracle共享游标的优点是:
l降低和减少Oracle对SQL的解析数量
l动态调整内存
l提高内存的使用率
风格请参照前面章节中的“建议的程序风格”
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
表的连接方式
FROM表顺序选择
如果是大于两表相关联,最好选择交叉表为驱动表,交叉表是指被其它表所引用的表。
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
RBO模式下,小表为驱动表的执行时间为大表是驱动的执行时间的:
0.078/2.253 = 2.26%!
驱动表的选择
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
此时的优化器模式为CBO,二者的执行时间仅仅相差:
0.328-0.313=0.015毫秒,二者几乎接近,这是为什么呢?我们再看二者执行计划:
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
我们发现,此时二者的执行计划 一模一样!这又是为什么?
驱动表的选择
驱动表(Driving Table)是指被最先访问的表,通常是以全表扫描的方式访问的。
无论如何,我们建议始终将记录小的表(如字典表)作为驱动表,则能适应CBO和RBO!
WHERE子句如何写
Oralce优化器的原理是采用自下而上的顺序解析WHERE子句,因此表之间的连接必须写在其他WHERE条件之前,
可过滤掉最大数量记录的条件必须写在WHERE子句的末尾 。
![高级SQL优化(一) <wbr>——《12年资深DBA教你Oracle开发与优化——性能优化部分》](http://simg.sinajs.cn/blog7style/images/common/sg_trans.gif)
上述SQL语句的例子虽然符合优化规范的比不符合优化规范的写法仅仅快了不到0.4秒,但重要的是这是在当前单机环境、且没有任何其它数据库事务、业务很简单、连接的表仅有两个表的情况下。如果在实际的大业务量环境下,则这种优化效应将成
倍数级增长!
因此,我们建议任何时候编写SQL语句时要 使用表的别名、
对表的连接永远
写在WHERE后面的第一个位置,并对过滤条件进行估算,
按照降序的大小将这些
条件从WHERE子句最后部分往前排列。
习题
1.SQL优化的步骤包含那几步?可以使用那几种工具或方法发现糟糕的SQL?
2.SQL调节的三大目标是什么?请举例来说明如何均衡负载。
3.一般来说,SQL优化包括三个阶段,分别是语法分析、优化和执行阶段。请问,语法分析阶段的主要任务是什么?Oracle在优化阶段优化器主要执行的任务和考虑的因素又分别包含哪些?
4.在SELECT少用*,多用具体的列名其理论依据是什么?
5.Truncate包含几种用法?画图并解释Truncate如何改变高水位线。
6.举例说明什么情况下应该尽量多用COMMIT,什么情况下不能。
7.使用DECODE合并多个相类似操作,其与减少对数据库的查询次数有关系吗?
8.应该避免那种不合适的通配符的使用方法?
9.解释什么是驱动表,应该如何选择驱动表。
10.推荐的FROM子句和WHERE子句应该如何写,并解释其原理。