设为首页 加入收藏

TOP

基于oracle的sql优化方法论(一)
2015-11-21 01:48:52 来源: 作者: 【 】 浏览:0
Tags:基于 oracle sql 优化 方法论
Oracle 数据库里SQL优化的终极目标就是要缩短目标SQL语句的执行时间。要达到上述目的,我们通常只有如下三种方法可以选择:
1、降低目标SQL语句的资源消耗;
2、并行执行目标SQL语句;
3、平衡系统的资源消耗。
“方法1:降低目标SQL语句的资源消耗”以缩短执行时间,这是最常用的SQL优化方法。这种方法的核心是要么通过在不更改业务逻辑的情况下改写SQL来降低目标SQL语句的资源消耗,要么不改SQL但通过调整执行计划或相关表的数据来降低目标SQL语句的资源消耗。
方法2:并行执行目标SQL语句”,这实际上是以额外的资源消耗来换取执行时间的缩短,很多情况下使用并行是针对某些SQL的唯一优化手段。
“方法3:平衡系统的资源消耗” 可以避免不必要的资源争用所导致的目标SQL语句执行时间的增长。对某些SQL而言,其执行时间的增长或者不稳定(时快时慢)不是由于其执行计划的问题,而是由于在目标SQL执行时系统处于高负荷状态,执行目标SQL所需要的硬件资源(CPU、内存、IO等)得不到保障,存在争用的情况。在这样的情况下,如果我们能平衡系统的资源消耗,把一些跟目标SQL同时执行的不重要但很消耗系统资源的操作(如报表、批处理等)挪到系统不忙的时候执行,比如把它们挪到晚上执行,那么就可以释放部分系统硬件资源以确保目标SQL执行时所需要的硬件资源不再存在争用的情况,进而就避免了其执行时间的增长或者不稳定。


对于有问题的SQL做SQL优化的具体步骤一般为:
1、查看该SQL语句的执行计划,并结合其资源消耗情况和相关统计信息、Trace文件来分析其执行计划是否合理;
2、通过修正措施(如调整该SQL的执行计划等)来对该SQL做调整以缩短其执行时间,这里调整的指导原则就是之前刚介绍的 Oracle数据库里做SQL优化通常会采用的三种方法。





统计信息的收集如何来做比较合理?
答:在Oracle数据库里,收集统计信息总的原则就是量体裁衣,即要找到适合自己 系统的统计信息收集策略,用尽量小的代价收集到能稳定跑出正确执行计划的统计信息即可,也就说收集到的统计信息不一定要特别准,只要具备代表性,能稳定跑出正确的执行计划就可以了。
根据上述指导原则,我们建议采用如下的收集策略:根据系统的类型及特点来决定是采用Oracle自带的自动统计信息收集作业还是自己写shell脚本来收集统计信息。对于那种数据量不大的OLTP类型的系统,建议是用前者。如果是数据量很大的OLAP或者DSS系统,建议自己写shell脚本来收集统计信息,因为对于这种系统而言,很多表的访问都是只有全表扫描这一种方式,这种情况下这些表的统计信息是否准确就无所谓了,甚至无须浪费资源和时间来对这些表收集统计信息,而是写shell脚本仅对那些需要收集统计信息的表和相关对象收集统计信息就可以了。
不管是采用自动统计信息收集作业还是手工写Shell脚本来收集统计信息,我们都需要特别注意如下注意事项:
(1)当系统中导入了大量数据后,如果要马上进行相关的业务处理,建议在进行相关的业务处理之前及时对相关表手工收集统计信息,因为这些被导入了大量数据的表已经来不及等到当天的自动统计信息收集作业自动收集统计信息了。
(2)某些新上线或新迁移的系统,其中的某些表在上线/迁移之初其数据量为0(所以其相关统计信息也为0),接着在导入少量数据(比如几千条)后马上进行相关的业务处理,建议在进行相关的业务处理之前及时对这些表手工收集统计信息。因为一来这些被导入了少量数据的表已经来不及等到当天的自动统计信息收集作业自动收集统计信息了,二来这些表的统计信息的初始值为0,所以即便随后导入的数据量并不大,但如果不及时收集统计信息的话也可能也会对相关SQL的执行计划产生颠覆性的影响。
这里需要注意的是:无论是用ANALYZE命令还是用DBMS_STATS包来收集统计信息,它们均会提交当前事务。如果应用对事务有强一致性的要求,同时在当前事务中在导入数据后又必须得在同一个事务中进行相关的后续业务处理,则可以在后续处理的相关SQL中加入Hint(或者使用SQL Profile/SPM来替换相关SQL的执行计划)以让Oracle走出理想执行计划而不再受统计信息正确与否的干扰。
(3)建议及时对包含日期型字段的表收集统计信息,避免谓词越界现象的出现。自动统计信息收集作业选取收集对象的标准,在默认情况下是目标表的delete+insert+update操作所影响的记录数已经超过了TAB$中记录的目标表总记录数的10%,或者是自上次自动统计信息收集作业完成之后目标表被执行过truncate操作。这种标准对于有日期型字段的大表而言,可能会显得过于宽松。
比如一个有日期型字段的表,每天向该表中导入当天的数据,同时该表中的数据保持一年,那么一年后该表新导入的数据仅占该表总记录数的1/365。这种情况下该表的那个日期型字段的统计信息很可能就是不准的,此时就非常容易出现谓词越界的现象,进而可能会严重影响相关SQL的执行计划。这种情况下我们的应对方法就是手工写shell脚本单独对该表每天收集统计信息,或者使用DBMS_STATS.SET_TABLE_PREFS来对自动统计信息收集作业中针对该表的收集设置做修改,比如用DBMS_STATS.SET_TABLE_PREFS将针对该表的STALE_PERCENT的值设为0(仅适用于Oracle 11g及其以上的版本)。
(4)收集统计信息的采样比例到底设为多少合适是一个永恒的话题,实际上这个问题是没有标准答案的,因为这个采样比例取决于执行收集统计信息作业被允许消耗的时间和系统的数据分布情况。如果时间允许,我们当然是希望将采样比例设为100%,因为这时收集到的统计信息肯定是最准的,但100%的采样比例所带来的问题就是收集统计信息作业的执行时间可能会非常长,甚至在规定的窗口期内跑不完。如果采样比例不能设为100%,那么设为多少合适则取决于系统数据的分布情况。例如,如果系统的数据分布十分均匀,则很可能用10%的采样比例所得到的统计信息就已经能让目标SQL跑出正确、稳定的执行计划了。也就是说,这种情况下得到的执行计划很可能和用100%的采样比例得到的执行计划是一样的,既然如此,为什么还要耗费额外的时间与资源去跑增加采样比例后的统计信息收集作业?但如果数据分布不均匀,此时同样采用了10%的采样比例,并且碰巧采样的这10%的数据块大多数都是空块或者是数据分布极不均衡、不具备代表性的数据块,则这种情况下得到的统计信息很可能就是不准的,甚至是错误的,也就是说这个时候就需要增加采样比例了。面对后一种情形,采样比例增加到多少合适呢?是20%,30%,50%还是更多?没有人可以告诉你答案,也许只能靠你自己不断的摸索和调整,直到收集统计信息作业既能在规定的窗口期内跑完同时目标SQL又能跑出正确的执行计划为止。
尽管如此,我们还是推荐一个统计信息收集作业采样比例的初始值:对于Oracle 11g及其以上的版本,收集统计信息的采样比例建议采用DBMS_STATS.AUTO_SAMPLE_SIZE。Oracle 11g中的AUTO_SAMPLE_SIZE采用了全新的哈希算法,它既能保证在较短的时间内执行
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇MongoDB数据库与MySQL操作 下一篇Oracle数据库分别在Windows/Linux..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: