ORACLE性能优化之SQL语句优化

文章来源:http://blog.csdn.net/jdzms23/article/details/23850783

版权声明:本文为博主原创文章,未经博主允许不得转载。

目录(?)[-]

  1. SQL语句执行过程
  1. 1 SQL语句的执行步骤
  2. 2 典型SELECT语句完整的执行顺序
  3. 3 SQL语句执行过程
  1. 优化器及执行计划
  1. 1 SQL优化方法论
  1. 合理应用Hints
  1. 1Hints
  1. 索引及应用实例
  1. 1什么是索引
  2. 2索引分类
  3. 3什么时候使用索引
  4. 4改写SQL使用索引
  5. 5索引应用
  1. 其他优化技术及应用
  1. 1其他优化技术及思路
  2. 2 SQL优化总结

操作环境:AIX +11g+PLSQL

包含以下内容:

1.  SQL语句执行过程

2.  优化器及执行计划

3.  合理应用Hints

4.  索引及应用实例

5.   其他优化技术及应用

1.SQL语句执行过程

1.1 SQL语句的执行步骤

  1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义。

  2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限。

  3)视图转换,将涉及视图的查询语句转换为相应的对基表查询语句。

  4)表达式转换, 将复杂的 SQL 表达式转换为较简单的等效连接表达式。

  5)选择优化器,不同的优化器一般产生不同的“执行计划”

  6)选择连接方式, Oracle 主要有三种连接方式,对多表连接ORACLE会选择适当的连接方式。

  7)选择连接顺序, 对多表连接 ORACLE 选择哪一对表先连接,选择这两表中哪张表做为基础数据表。

  8)选择数据的搜索路径,根据以上条件选择合适的数据搜索路径,比如,是选用全表搜索还是利用索引或是其他的方式。

  9)运行“执行计划”

我们可以通过如下语句来查询缓存中的执行计划:

[sql] view plain copy

 

  1. SELECT t1.*,  
  2.          't2-->',  
  3.          t2.*  
  4.     FROM v$sql_plan t1  
  5.     JOIN v$sql t2  
  6.       ON t1.address = t2.address  
  7.      AND t1.hash_value = t2.hash_value  
  8.      AND t1.child_number = t2.child_number;--缓存中的执行计划。  

1.2 典型SELECT语句完整的执行顺序

  1)from子句组装来自不同数据源的数据;

  2)where子句基于指定的条件对记录行进行筛选;

  3)group by子句将数据划分为多个分组;

  4)使用聚集函数进行计算;

  5)使用having子句筛选分组;

  6)计算所有的表达式;

  7)计算select的字段;

  8)使用order by对结果集进行排序。

1.3 SQL语句执行过程

如下图所示:

说明:

*这是一张SQL语句执行过程图

*执行计划是SQL语句执行过程中必然用到的

*执行计划是优化器(Optimizer)的产物

*两种不同的方式:CBO和RBO

查看优化器设置:

方法一:

[sql] view plain copy

 

  1. SELECT VALUE FROM v$parameter t WHERE t.name = 'optimizer_mode';  

方法二(SQLPLUS下执行):

[sql] view plain copy

 

  1. showparameter optimizer_mode  

*CBO用到了字典中的Statistics,而RBO没有

分析统计信息相关SQL:

[sql] view plain copy

 

  1. analyze table tablename compute statistics;  

[sql] view plain copy

 

  1. analyze table tablename compute statistics for all indexes  

[sql] view plain copy

 

  1. analyze table tablename delete statistics   

2.优化器及执行计划

2.1 SQL优化方法论

*ORACLE10g以后的版本,SQL优化的本质是基于对CBO和执行计划的深刻理解,进入CBO时代,一定要理解执行计划。

*查看执行计划有好多方式,比如使用PL/SQL Developer工具,选中select语句,按F5键就可以显示其执行计划,不过显示的不完全

*最好使用在Oracle官方的sqlplus工具,性能最好,方便直观,下面介绍两种查看执行计划方式(也是最简单的两种方式)

关于执行计划的一些知识:

* Full Table Scans 全表扫描

* Rowid Scans  rowid扫描

* Index Scans 索引扫描

* Index Unique Scans

* Index Range Scans

* Index Range Scans Descending

* Index Skip Scans

* Full Scans

* Fast Full Index Scans(CBO)

* Index Joins

* Bitmap Joins

* Cluster Scans  簇扫描

* Hash Scans   散列扫描

* Sample Table Scans  表取样扫描

²在RBO时代,关于access path,很简单,有index就用,而对于join方法,编程人员一般会通过调整关联表之间的先后顺序来获得比较好的运行结果。有什么缺点呢?

²有了CBO,简单就是两个字-----CBO走的是包办婚姻:你的事交给我办。

ORACLE默认情况下,周一到周五每天晚上10点到第二天早上6点以及整个周末期间会自动收集统计信息

可以查看参数:

[sql] view plain copy

 

  1. show parameter STATISTICS_LEVEL  

²问题:CBO执行计划依赖的statistic不准确(缺失或者太旧),导致在计算执行成本时就会出现偏差,很可能会产生错误的执行计划,怎么办呢?

第一步:重新收集统计信息!

第二部:第一部解决不了的情况下,使用Hints

3.合理应用Hints

3.1Hints

慎用hint,可能会产生严重的后果,比如append会产生锁块,导致并发资源等待等

Hints的分类:

*Hints forOptimization Approaches and Goals(4)

    /*+ ALL_ROWS */

    /*+ FIRST_ROWS ( n )*/

    /*+ CHOOSE */

    /*+ RULE */

*Hints for AccessPaths(12)

    /*+ FULL ( table ) */

    /*+ INDEX ( tableindex) */

    /*+ INDEX_ASC ( tableindex) */

    /*+ INDEX_COMBINE (table index) */

    /*+ INDEX_JOIN (table index) */

    /*+ INDEX_DESC (table index) */

    /*+ INDEX_FFS ( tableindex) */

    /*+ NO_INDEX ( tableindex) */

    /*+ AND_EQUAL ( tableindex index) */

*Hints for QueryTransformations(10)

*Hints for JoinOrders(2)

*Hints for JoinOperations(11)

    /*+ USE_NL ( table )*/

    /*+ USE_MERGE ( table) */

    /*+ USE_HASH ( table) */

    /*+ LEADING ( table )*/

*Hints for ParallelExecution(5)

*Additional Hints(13)

以下为使用Hints的例子

[sql] view plain copy

 

  1. create table t_1(owner varchar2(30),table_name varchar2(30));  
  2. create table t_2(owner varchar2(30),table_name varchar2(30));  
  3. insert into t_1 SELECT owner,table_name FROM dba_tables;  
  4. insert into t_2 SELECT owner,view_name  FROM dba_views t;  
  5. create index idx_t_1 on t_1(table_name);  
  6. create index idx_t_2 on t_2(table_name);  
  7. analyze table t_1  compute statistics;   
  8. analyze table t_2  compute statistics;   
  9.   
  10. SELECT *  
  11.   FROM (SELECT * FROM t_1  
  12.         UNION ALL  
  13.         SELECT * FROM t_2) aa  
  14.  WHERE aa.table_name LIKE 'Z%';                 ---- Full Table Scans  
  15.    
  16. SELECT /*+ index(AA.t_1 idx_t_1) index(AA.t_2 idx_t_2)*/ *  
  17.   FROM (SELECT * FROM t_1  
  18.         UNION ALL  
  19.         SELECT * FROM t_2) AA  
  20.  WHERE AA.table_name LIKE 'Z%';               ---- Index Scans  

贴上执行图:

4.索引及应用实例

4.1什么是索引

*Oracle的索引是一种自平衡的B*Tree存储结构,其基本存储单位为数据块,称之为节点,共有三种类型的节点:根(root)节点,分枝(Branch)节点,叶(leaf)节点。

*分枝节点存储{索引值,键值对应下一级节点块地址,lmc指针}

*叶节点存储{索引值及其rowid,当前节点的前后节点的数据块地址}

所有叶节点上的两个指针形成一个双向链表,在这个双向链表上的所有索引值,从小到大排列,而对于倒序desc索引,则是从大到小排列

B*TREE索引图:

4.2索引分类

逻辑上: 

Single column 单列索引

Concatenated 多列索引

Unique 唯一索引

Non-Unique 非唯一索引

Function-based函数索引

Domain 域索引

物理上: 

Partitioned 分区索引

Non-Partitioned 非分区索引

B*tree:

  Normal 正常型B树

  ReverseKey 反转型B树

  Bitmap 位图索引

4.3什么时候使用索引

*如果要检索全表,不必要建索引,因为索引会带来额外的IO操作。

*如果检索的记录数占全部表记录的10%以下可以考虑建索引(大表)。

*表之间的关联字段可以考虑建索引,特别是一张大表和一张小表的关联。

*B*Tree索引适合于大量的增、删、改(OLTP);

     不适合用包含OR操作符的查询;一般不适用NULL判断;

     适合高基数的列(重复值少)

*Bitmap索引适合于决策支持系统OLAP;

    做UPDATE代价比较高;会锁块;

    非常适合OR操作符的查询;

    适合低基数的列(比如,只有Y和N两种值) ;

*Reverse索引反转了b*tree索引码中的字节,是索引条目分配更均匀,多用于并行服务器环境下,用于减少索引叶的竞争。

    索引是’双刃剑’,在查询与DML之间寻求平衡

4.4改写SQL使用索引

*普通索引列 a is not null 按逻辑改为a>0或a>''

*like操作改写

*能用union all绝不用union,除非要去重

*in操作虽然简单易懂,但oracle内部会转换为表连接查询,使用in会多一步转换操作,所以建议使用表关联查询

*not in 强烈建议使用not exists或(外连接+判断为空)

*<>(不等于)操作不走索引,推荐a<>0改为(a>0 ora<0)    a<>’’改为a>’’

*提防隐式类型转换, oracle内部处理a=0与a=‘0’是完全不同的,甚至会导致不走索引,这个深有体会,最近一个项目就是这个隐式类型转换出了问题,导致速度

很慢

4.5索引应用

例1.用合适的索引来避免不必要的全表扫

    如果要在索引列查询is not null条件,建议列加上is not null约束,默认值约束,

    然而确实由于某种原因索引列设计为null,还想通过is null条件走索引,该如何是好呢?请看

[sql] view plain copy

 

  1. drop table t_tab1;  
  2. create table t_tab1 as   
  3.     SELECT t.owner,  
  4.        t.object_name,  
  5.        t.object_type,  
  6.        t.created,  
  7.        t.last_ddl_time  
  8.     FROM dba_objects t;  
  9. analyze table t_tab1  compute statistics;  
  10. create index idx01_t_tab1 on t_tab1(last_ddl_time);--普通索引  
  11. set autotrace trace;  
  12. SELECT * FROM t_tab1 t where t.last_ddl_time is null;  

执行计划如下图:

如上情况调整为复合索引

[sql] view plain copy

 

  1. drop index idx01_t_tab1;  
  2. create index idx01_t_tab1 on t_tab1(last_ddl_time,1);--加了个常量  
  3. set autotrace trace;  
  4. SELECT * FROM t_tab1 t where t.last_ddl_time is null;  

执行计划如下图:

 例2:用合适的函数索引来避免看似无法避免的全表扫描

[sql] view plain copy

 

  1. drop table t_tab1 purge;  
  2. create table t_tab1 as   
  3.         SELECT t.owner,  
  4.             t.object_name,  
  5.         t.object_type,  
  6.         t.OBJECT_ID,  
  7.         t.created,  
  8.         t.last_ddl_time  
  9.     FROM dba_objects t;  
  10. CREATE INDEX IDX01_T_TAB1 ON T_TAB1(object_name);  
  11. analyze table t_tab1  compute statistics;   
  12. set autot trace  
  13. SELECT * FROM t_tab1 t where t.object_name like '%20121231';  

执行计划如下:

改进索引,此处使用反转函数索引,此外经常用到的函数索引还有,instr(),substr()等

[sql] view plain copy

 

  1. drop index IDX01_T_TAB1;  
  2. CREATE INDEX IDX02_T_TAB1 ON T_TAB1(reverse(object_name));  
  3. analyze table t_tab1  compute statistics;   
  4. SELECT * FROM t_tab1 t where reverse(t.object_name) like reverse('%20121231');  

执行计划如下:

5.其他优化技术及应用

5.1其他优化技术及思路

并行技术,并行执行目标SQL语句,这实际上是以额外的资源消耗来换取执行时间的缩短,很多情况下使用并行是针对某些SQL的唯一优化手段。

使用shell调度或其他调度工具。

      SQL语句级别的并行:/*+parallel*/

       /*+ parallel(table_name 4)*/

表压缩技术

  compress

NOLOGGING

  减少日志

Partition技术

  分而治之

中间表/临时表事务分解思路

  ‘大事化小’ 

求平衡

    CPU,Memory很强大,IO存在瓶颈(最普遍的情况)

使用新特性

     insertall 啦       使用listagg()比wm_concat()快大概50倍、row_number()等分析函数

软硬件资源合理搭配

       黔驴技穷,要求加硬件资源? Boss会对你说,找会计去吧,提前给你开工资 ……

5.2 SQL优化总结

SQL的优化的手段是五花八门、不一而足的,包括但不限于如下措施:

*如果是统计信息不准或是因为CBO计算某些SQL的执行路径(Access Path)的成本所用公式的先天不足而导致的SQL性能问题,

 我们可以通过重新收集统计信息或者手工修改统计信息或者使用Hint来加以解决;

*如果是SQL语句的写法问题,我们可以通过在不更改业务逻辑的情况下改写SQL来加以解决;

*如果是不必要的全表扫描/排序而导致了目标SQL的性能问题,我们可以通过建立合适的索引(包括函数索引、位图索引等)来加以解决;

*如果是表或者索引的不良设计导致的目标SQL的性能问题,我们可以通过重新设计表/索引,重新组织表里的数据来加以解决;

*如果上述调整措施都失效,我们可以考虑用并行来缩短目标SQL的执行时间;

*如果上述调整措施、包括并行都失效,我们还可以在联系实际业务的基础上更改目标SQL的执行逻辑,甚至不执行目标SQL,这是最彻底的优化:)

时间: 2024-08-22 07:38:54

ORACLE性能优化之SQL语句优化的相关文章

Oracle中的sql语句优化

1.选择最有效率的表名顺序(只在基于规则的优化器中有效)ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表driving table)将被最先处理,在FROM子句中包含多个表的情况下,必须选择记录条数最少的表作为基础表.如果有3个以上的表连接查询,那就需要选择交叉表(intersection table)作为基础表 , 交叉表是指那个被其他表所引用的表. 2.WHERE子句中的连接顺序ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理表

oracle sql语句优化(转载)

(1)      选择最有效率的表名顺序 ( 只在基于规则的优化器中有效 ) : ORACLE 的解析器按照从右到左的顺序处理 FROM 子句中的表名, FROM 子句中写在最后的表 ( 基础表 driving table) 将被最先处理,在 FROM 子句中包含多个表的情况下 , 你必须选择记录条数最少的表作为基础表.如果有 3 个以上的表连接查询 , 那就需要选择交叉表 (intersection table) 作为基础表 , 交叉表是指那个被其他表所引用的表 . (2)      WHER

SQL语句优化提高数据库性能_MsSql

性能不理想的系统中除了一部分是因为应用程序的负载确实超过了服务器的实际处理能力外,更多的是因为系统存在大量的SQL语句需要优化.为了获得稳定的执行性能,SQL语句越简单越好.对复杂的SQL语句,要设法对之进行简化. 常见的简化规则如下: 1)不要有超过5个以上的表连接(JOIN) 2)考虑使用临时表或表变量存放中间结果 3)少用子查询 4)视图嵌套不要过深,一般视图嵌套不要超过2个为宜 一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出S

SQL语句优化提高数据库性能

性能不理想的系统中除了一部分是因为应用程序的负载确实超过了服务器的实际处理能力外,更多的是因为系统存在大量的SQL语句需要优化.为了获得稳定的执行性能,SQL语句越简单越好.对复杂的SQL语句,要设法对之进行简化. 常见的简化规则如下: 1)不要有超过5个以上的表连接(JOIN) 2)考虑使用临时表或表变量存放中间结果 3)少用子查询 4)视图嵌套不要过深,一般视图嵌套不要超过2个为宜 一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出S

秋色园QBlog技术原理解析:性能优化篇:打印页面SQL,全局的SQL语句优化(十三)

文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色园QBlog技术原理解析:UrlRewrite之无后缀URL原理(三) --介绍如何实现无后缀URL 4: 秋色园QBlog技术原理解析:UrlRewrite之URL重定向体系(四) --介绍URL如何定位到处理程序 5: 秋色园QBlog技术原理解析:Module之页面基类设计(五) --介绍创建

oracle数据库优化辅助SQL语句_oracle

具体详情请看下文代码分析. --查询正在执行的SQL语句 SELECT OSUSER 电脑登录身份, PROGRAM 发起请求的程序, USERNAME 登录系统的用户名, SCHEMANAME, B.Cpu_Time 花费cpu的时间, STATUS, B.SQL_TEXT 执行的sql, B. FROM V$SESSION A LEFT JOIN V$SQL B ON A.SQL_ADDRESS = B.ADDRESS AND A.SQL_HASH_VALUE = B.HASH_VALUE

sql语句优化之SQL Server(详细整理)_MsSql

MS SQL Server查询优化方法 查询速度慢的原因很多,常见如下几种 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6.查询出的数据量过大(可以采用多次查询,其他的方法降低数据量) 7.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 8.sp_lock,sp_who,活动的用户查看,原因是读写竞争资源. 9.返回了不必要的行和列 10.查询语句不好,

sql语句优化分享

sql语句优化分享 这是查询学生数据的逻辑,逻辑比较有点乱,这个查询跑30分钟也不会出结果,一执行CPU立马100%,虽然是个虚似机,但也不至于这种查询也对付不了,肯定有优化的地方.     SELECT  *        FROM 学生表 WITH(NOLOCK) WHERE          (FromSys IS NULL OR          (             (FromSys<>'A' AND FromSys<>'B' AND FromSys<>

基于索引的SQL语句优化之降龙十八掌

  From:www.oracle.com.cn 基于索引的SQL语句优化之降龙十八掌 1        前言        2 2        总纲        2 3        降龙十八掌        3第一掌避免对列的操作        3第二掌避免不必要的类型转换        4第三掌增加查询的范围限制        4第四掌尽量去掉"IN"."OR"        4第五掌尽量去掉 "<>"        5第六