SQL优化总结
SQL 的优化主要涉及几个方面:
(1) 
(2) 
(3) 
 
一.SQL 编写注意事项
 
对于生产环境上的SQL,能够从AWR 或者 Statspack 报告中获取相关的SQL 信息。
 
这部分參考:
http://blog.csdn.net/tianlesoftware/article/details/4682300
 
http://blog.csdn.net/tianlesoftware/article/details/4682329
 
 
 
1.2 SQL 编写的详细注意事项
 
在SQL 编写过程中, 避免一些低效的写法。能将SQL的效率提高几倍。 如:
 
to_char(created,'yyyy') = '2011'
trunc(created,'y') = to_date('01-jan-2011','dd-mon-yyyy')
 
与使用TRUNC 相比。使用TO_CHAR 所用的CPU 时间与前者相差一个数量级(即相差12倍)。由于TO_CHAR 必须把日期转换为一个串。这要使用一个更大的代码路径。并利用当前的全部NLS来完毕这个工作。然后必须运行一个串与串的比較。还有一方面。TRUNC 仅仅需把后5 个字节设置为1.然后将两个7 字节的二进制数进行比較。因此。假设仅仅是要截断一个DATE 列。你将应该避免使用TO_CHAR。
 
之前从网上转载了一篇文章。链接例如以下:
http://blog.csdn.net/tianlesoftware/article/details/4672023
 
这是几年前转载的文章,当中内容有些也有误。这里就不更正了。
 
1.3 多表关联方式
 
(1) 
Inner table 循环与outer table匹配。这样的是表有索引,选择性较好。表之间的差距不大。 ===》两层for 循环,小表匹配大表。
(2) 
小表做hash ,放内存,然后拿大表的每条记录做hash,然后与之前小表的Hash 值匹配。
==》大表匹配小表。
(3) 
表有序。而且没有索引。
 
详细參考:
 
 
 
二. 相关理论说明
2.1 Oracle 优化器:CBO 和 RBO
Oracle 
 
 
 
CBO(Cost Based Optimizer)的思路是让Oracle 
 
 
当表没有做分析的时候。Oracle 
 
相关链接:
http://blog.csdn.net/tianlesoftware/article/details/5824886
 
Oracle CBO 
http://blog.csdn.net/tianlesoftware/archive/2010/07/11/5709784.aspx
 
http://blog.csdn.net/tianlesoftware/article/details/5845028
 
 
2.2 软解析和硬解析
Oracle对此SQL将进行几个步骤的处理过程:
 
 
 
 
 
当中解析分为:
 
 
 
 
 
 
 
注:创建解析树、生成运行计划对于sql的运行来说是开销昂贵的动作,所以,应当极力避免硬解析。尽量使用软解析。
这就是在非常多项目中,倡导开发设计人员对功能同样的代码要努力保持代码的一致性,以及要在程序中多使用绑定变量的原因。
 
Soft 
 
Oracle SQL的硬解析和软解析
http://blog.csdn.net/tianlesoftware/archive/2010/04/08/5458896.aspx
 
http://blog.csdn.net/tianlesoftware/article/details/6628232
 
Oracle SQL Parsing FlowDiagram(SQL 解析流程图)
http://blog.csdn.net/tianlesoftware/article/details/6625683
 
那么运行计划放在内存的什么位置。在一下的Blog 有说明:
http://blog.csdn.net/tianlesoftware/article/details/6629869
 
与解析相关的一个重要參数:cursor_sharing,它决定什么情况下使用同样的cursor,从某种意义上讲,决定是否须要进行解析,该參数有3个值:
 
 
 
 
 
 
 
http://blog.csdn.net/tianlesoftware/article/details/6551723
 
2.3 运行计划
生成SQL的运行计划是Oracle在对SQL做硬解析时的一个很重要的步骤,它制定出一个方案告诉Oracle在运行这条SQL时以什么样的方式訪问数据:索引还是全表扫描,是Hash Join还是Nested loops Join等。 
 
Oracle 运行计划(Explain Plan) 说明
http://blog.csdn.net/tianlesoftware/article/details/5827245
 
http://blog.csdn.net/tianlesoftware/article/details/6556850
 
http://blog.csdn.net/tianlesoftware/article/details/6561620
 
我们也能够使用OracleHint 来强制的改变SQL的运行计划。当然Oracle 不建议这么做,由于仅仅要统计信息正确的情况下,CBO 的分析就过一般都是正确的。
http://blog.csdn.net/tianlesoftware/article/details/5833020
 
2.4 10053 和 10046 事件
2.4.1 10053事件
我们在查看一条SQL的运行计划的时候,仅仅能看到CBO 
 
10053事件就提供了这种功能。它产生的trace文件提供了Oracle怎样选择运行计划,为什么会得到这种运行计划信息。
 
对于10053事件的trace文件,我们仅仅能直接阅读原始的trace文件,不能使用tkprof工具来处理,tkprof工具仅仅能用来处理sql_trace 
 
10053事件有两个级别:
 
Column statistics
Single Access Paths
Join Costs
Table Joins Considered
Join Methods Considered (NL/MS/HA)
 
Parameters used by the optimizer
Index statistics
 
启用10053事件:
ALTER SESSION SET EVENTS='10053 trace namecontext forever, level 1';
ALTER SESSION SET EVENTS='10053 trace namecontext forever, level 2';
 
关闭10053事件:
ALTER SESSION SET EVENTS '10053 trace namecontext off';
 
 
说明:
(1)sqlplus中打开autotrace看到的运行计划实际上是用explain plan 
应该通过v$sql_plan查看SQL的真实的运行计划。
(2)10053仅仅对CBO有效。并且假设一个sql语句已经解析过,就不会产生新的trace信息。
 
2.4.2 10046 事件:
10046 
 
10046 
Level 1: 
Level 4: 
Level 8: 
Level 12:等同于Level 4+Level 8, 
 
 
-- 
SQL>alter session set events ‘10046 trace name context off’; 
也能够使用oradebug 命令来运行10046:
SYS@anqing1(rac1)> oradebug setmypid
SYS@anqing1(rac1)> oradebug event 10046trace name context forever,level 8;
SYS@anqing1(rac1)> oradebug event 10046trace name context off;
SYS@anqing1(rac1)> oradebugtracefile_name
/u01/app/oracle/admin/anqing/udump/anqing1_ora_17800.trc
 
详细的内容參考:
Oracle oradebug 命令 使用说明
http://blog.csdn.net/tianlesoftware/article/details/6525628
 
Oracle 
http://blog.csdn.net/tianlesoftware/article/details/4977827
 
http://blog.csdn.net/tianlesoftware/article/details/5859027
 
Event 10053 运行计划绑定变量 Bind peeking
http://blog.csdn.net/tianlesoftware/article/details/5544307
 
Oracle SQL Trace 和 10046 事件
http://blog.csdn.net/tianlesoftware/article/details/5857023
 
http://blog.csdn.net/tianlesoftware/article/details/5632003
 
2.5 统计信息
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
统计信息收集例如以下数据:
(1)表自身的分析: 
(2)列的分析:包含列值的反复数,列上的空值,数据在列上的分布情况。
(3)索引的分析: 
 
这些统计信息存放在数据字典里,如:
(2). 
(3). 
(4). 
(5). 
(6). 
(7). 
(8). 
(9). 
(10). 
(11). 
(12). 
(13). 
(14). 
(15). 
(16). 
 
统计信息的准确程度,直接决定SQL的效率。
 所以须要定期的收集相关对象的统计信息。Oracle 
 
Oracle 
 
 
 
该Job 
该过程首先检測统计信息缺失和陈旧的对象。然后确定优先级。再開始进行统计信息。
 
Scheduler Job的 
 
Gather_stats_job 
(1)对象的统计信息之前没有收集过。
(2)当对象有超过10%的rows 
 
Oracle Statistic 统计信息 小结
http://blog.csdn.net/tianlesoftware/article/details/4668723
 
http://blog.csdn.net/tianlesoftware/article/details/6445868
 
 
三.索引
3.1 索引分类
索引对DB的性能中起着关键的数据。
Oracle 有例如以下类型的索引:
B树索引(默认类型)
位图索引
HASH索引
索引组织表索引
反转键(reverse 
基于函数的索引
分区索引(本地和全局索引)
位图连接索引
 
3.2 索引限制
这部分内容应该放到SQL 编写部分。只是为了强调。还是放到这块。
 
即使相关字段上有索引,在例如以下4种情况,也不会走作引:
(1) 
(2) 
(3) 
(4) 
 
所以在SQL 编写过程中,尽量避免以上4种情况。
 
详细參考:
Oracle 索引具体解释
http://blog.csdn.net/tianlesoftware/article/details/5347098
 
3.3 索引维护
这部分内容包含:
(1)  
(2) 索引的扩展:index segment 是由extents组成。假设extents大于10,能够考虑重建索引。
(3) 索引碎片:查询index_stats表以确定索引中删除的、未填满的叶子(Leaf)行的百分比 和 height 字段。
假设索引的叶子行的碎片超过10%,或者 index_stats中height > =4, 能够考虑对索引进行重建。
 
 
详细參考:
索引维护:
http://blog.csdn.net/tianlesoftware/article/details/5680706
 
3.4 索引的 Clustering Factor 參数
 
那么Oracle 为什么不走索引? 非常可能就是和这个參数值有关。
 
 
 
 
 
 
解决问题的唯一方法就是对表进行move。
 
详细參考:
Oracle Index Clustering Factor 说明
http://blog.csdn.net/tianlesoftware/article/details/6585453
 
3.5 索引扫描5种类型:
(1)index unique scan: 
(2)index range scan: 查询结果返回多行记录。
 
(3)index full scan:可能进行全Oracle索引扫描而不是范围扫描,须要注意的是全Oracle索引扫描仅仅在CBO模式下才有效。  
 
(4)index fast full scan: 与 index full scan非常类似,可是一个显著的差别就是它不正确查询出的数据进行排序,即数据不是以排序顺序被返回。在这样的存取方法中。能够使用多块读功能,也能够使用并行读入,以便获得最大吞吐量与缩短运行时间。
 
(5)index skip scan: INDEX SKIP SCAN,发生在多个列建立的复合索引上。假设SQL中谓词条件仅仅包括索引中的部分列,而且这些列不是建立索引时的第一列时。就可能发生INDEX SKIP SCAN。这里SKIP的意思是由于查询条件没有第一列或前面几列,被忽略了。
 
详细參考:
Oracle 索引扫描的五种类型
http://blog.csdn.net/tianlesoftware/article/details/5852106
 
四.绑定变量
这个也是SQL 编写的基本功. 
 
Oracle里的全部SQL 语句都是implicitly sharable的。 SQL 在运行之前,要通过一个hash 运算。生成相关的cursor。
假设通过hash 运算之后,发现已经了有相应的cursor,那就能够直接使用之前的cursor 和plan。
假设不存在,就须要进行硬解析,而硬解析是一个很耗资源的操作。须要尽量降低硬解析。
怎样保证每次HASH 运算之后的hash 值都一样,那么这就须要通过绑定变来来实现。
 
在第一次运行运行SQL 之后,如果使用了绑定变量。那么Oracle 在硬解析的时候。会进行一个叫Peek的操作。 也能够称为偷窥。就是把实际值带进去,帮助产生更加准确的运行计划。比方相应的Peek列上有严重的数据倾斜,如果我们已经对表进行了统计信息收集,oracle 会产生该列的直方图(histogram),在peek的时候。就会依据直方图来决定,是走索引还是走全表扫描更划算。
 
因此第一运行产生的运行计划肯定是最优的。如今如果数据倾斜有2个值,一个占90%。一个占10%。 我们第一使用10%的值,所以第一次走索引。
那么如果我们以后在绑定时,使用了90%的值,那么这时候。Oracle 还是会使用之前的cursor,继续走索引,此时走索引就不是最优的了。
这个就是Oracle 10g里绑定变量的一个问题。 在第一次硬解析之后,以后全部的操作都会使用之前产生的cursor 和plan。
所以在10g里。对于列上有严重数据倾斜的,最好是不採用绑定变量。
 
在Oracle 11g里,对这个问题,进行了优化,使用了Adaptive Cursor Sharing,它能够产生多个共享cursor。
假设是90%的值,就使用cursor 1,假设是10%的cursor,就使用corsor 2. 在这个转换的过程中还是有可能再次产生硬解析。
 
Oracle 11g的绑定变量处理步骤例如以下:
 
 
 
 
 
 
 
 
http://blog.csdn.net/tianlesoftware/article/details/5856430
 
http://blog.csdn.net/tianlesoftware/article/details/6324243
 
Oracle 10g 与 11g 绑定变量(Bind Variable) 差别 说明
http://blog.csdn.net/tianlesoftware/article/details/6591222
 
对于绑定变量的cursor 是否能重用,与Cursor_sharing 參数有非常大关系。详细參考:
http://blog.csdn.net/tianlesoftware/article/details/6551723
 
http://blog.csdn.net/tianlesoftware/article/details/6629869
 
 
五.其它与SQL 性能相关的链接
 
http://blog.csdn.net/tianlesoftware/article/details/5995051
 
http://blog.csdn.net/tianlesoftware/article/details/6599003
 
http://blog.csdn.net/tianlesoftware/article/details/6578351
 
Oracle Pipelined TableFunctions 与 性能优化 说明
http://blog.csdn.net/tianlesoftware/article/details/6601540
 
Oracle arraysize 和 fetchsize 參数 与 性能优化 说明
http://blog.csdn.net/tianlesoftware/article/details/6579913
 
http://blog.csdn.net/tianlesoftware/article/details/6576156
 
Oracle Parallel Execution(并行运行)
http://blog.csdn.net/tianlesoftware/article/details/5854583
来源:http://blog.csdn.net/tianlesoftware/article/details/7008801
很多其它的关于sql优化的能够查看以上链接总结
 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号