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优化的能够查看以上链接总结