找回密码
 注册账号

QQ登录

只需一步,快速开始

手机号码,快捷登录

手机号码,快捷登录

初学者课程:T3自学|T6自学|U8自学软件下载课件下载工具下载资料:通资料|U8资料|NC|培训|年结积分规则 | 使用常见问题Q&A
知识库:U8 | | NC | U9 | OA | 政务U8|U9|NCC|NC65|NC65客开|NCC客开新手必读 | 任务 | 快速增金币用友QQ群[微信群]
查看: 7123|回复: 16

[经验] Oracle中的SQL语句的十大优化

[复制链接]
发表于 2008-12-23 18:23:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册账号

×
在开发后台程序中,怎么样优化你的SQL语句使得你的后台程序能达到高效的目的,当然通过搜索这类相关文章有很多很多,这里本人写的是通过项目中总结出的十大主要SQL性能优化,希望在开发中能给大家一定的参考。

       下面的实例中使用3个表 (TABLE) A(R1,R2,R3,R4,R5,C1,C2,B2) B(R1,B1,B2) C(R1,C1,C2,B2),括号中即为表中的字段。

一、使用特定表中的索引。

       有时候一个表中的数据量很大时候,索引是非常非常的重要,何为索引?我来举个例子,你一听就能明白,比如:你想搜索我的电脑中一个名字为FILE.TXT文件,如果不知道该文件所在的目录(没有创建索引)情况下,基本上要扫描我的电脑中的所有盘符里的文件,如果你的硬盘中的有很多文件(相当一个表中有很多的数据),基本上是一个全盘扫描的过程,这时如果你告诉搜索,你的文件就在D盘的TEST目录下,这样来搜索速度将会大大的提高,给文件定位就相当一个索引。

       好了,知道索引是干什么之后,下面来看看怎么走正确的索引,才能达到最高效。假如A表中有两个索引IDX_R1 INDEX(R1,R2,R4,R5),IDX_R3 INDEX(R1,R3,R4,R5) 现在需要做这样的操作,显示表中的条件值是R1 = 1,R3 = 3,R4 =4的所有内容。通常我们会写出下面的查询语句。
    select * from A where R1 =1 and R3 =3 and R4;
按道理它走的索引是IDX_R3,有时候默认走的索引并不是你想象中的那样,特别是多表关联的情况下。所以我们进行指定一下索引,按我们真正想要的走的索引:
   select /*+ index(R1,IDX_R3) */* from A where R1 =1 and R3 =3 and R4;

二、在检索数据的时候两个表的关联查询效率低于使用EXISTS子句。
   SELECT  B.R1,B.B1,B.B2 FROM A,B WHERE A.R1 = B.R1;
   优化为:
   SELECT  B.R1,B.B1,B.B2 FROM B WHERE EXISTS(SELECT 1 FROM A WHERE A.R1 = B.R1);
   如果你在WINDOWS的ORACLE的平台可以使用PL/SQL中的执行计划(EXPLAIN PLAN),看一下相应的执行时间进行验证。

三、ORACLE的解析器是由右向左进行解析,所以在检索两个或以上表相关联的数据的时候,将数据量小的表放到最后让解析器优先解析。此方法在两个表的数据相差很大的情况下,会有点效果。

四、 使用EXISTS代替IN子句,同理用NOT EXISTS 代替NOT IN

因为使用IN子句作为一个查询条件后,ORACLE会将IN子句的数据先搜索出来以后,等结果集返回以后才作为一个条件值。而EXISTS语句是WHERE语句之前的数据优先检索完后在去检索EXISTS子句的内容。

五、如果有子句比较的情况下,将此比较语句放到WHERE后作为第一个条件。
如:

SELECT A.R2 FROM A WHERE B.B2 = 3 AND 2< SELECT COUNT(1) FROM B WHERE B.R1 = A.R1;  //效率较低

SELECT A.R2 FROM A WHERE 2< SELECT COUNT(1) FROM B WHERE B.R1 = A.R1 AND B.B2 = 3;  //效率较高

六、在写存储过程的时候,无论是执行UPDATE,还是执行INSERT,应该尽快的COMMIT。

七、在执行数据检索的过程中近可能少的访问同一个表。

在写存储过程的时候,有时候因为条件值不一样,通常需要多次的去访问同一个表,这个时候可以考虑一个使用DECODE函数来代替多个条件。

//1
SELECT SUM(Nvl(C2,0)) FROM C WHERE R1 = 12 AND C1 = 22 ;
//2
SELECT SUM(Nvl(C2,0)) FROM C WHERE R1 = 12 AND C1 = 33 ;

优化方法:
SELECT SUM(DECODE(C1,22,C2,33,C2,0) FROM C WHERE R1 =12 AND C1 IN(22,33);

八、在写条件的时候尽量在条件值的左边使用函数。
如:

SELECT * FROM A WHERE TO_CHAR(R5,'YYYYMM') = '200804'

应该使用

SELECT * FROM A WHERE R5 = TO_DATE('200804','YYYYMM');代替


九、UPDATE语句写法提高效率。

UPDATE A
SET C2 = (SELECT MAX(C2) FROM C),
    B2 = (SELECT MAX(B2) FROM C)
WHERE R1 = 1000;
高效:
UPDATE A
SET (C2, B2)
= (SELECT MAX(C2) , MAX(B2)
FROM C)
WHERE R1 = 1000;


十、用EXISTS替换DISTINCT.

例如:
//低效:
SELECT DISTINCT C.R1,C.B2
FROM A,C
WHERE A.R1 = C.R1 ;

//高效:
SELECT C.R1,C.B2
FROM C
WHERE EXISTS ( SELECT ‘X’
FROM A
WHERE A.R1 = C.R1);

EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.

Oracle中的SQL语句的十大优化.doc

31.5 KB, 下载次数: 19, 下载积分: 金币 -5

金币

快速加金币

下载提示积分金币不足,非特定用户等

无法下载,可充值金币

发表于 2008-12-24 09:32:09 | 显示全部楼层
发表于 2008-12-24 10:17:10 | 显示全部楼层
好东西!确实不错啊.......
发表于 2008-12-24 10:17:21 | 显示全部楼层
五、如果有子句比较的情况下,将此比较语句放到WHERE后作为第一个条件。
什么原理?
发表于 2008-12-24 10:21:51 | 显示全部楼层
十、用EXISTS替换DISTINCT.
中使用到的例子不是两条同等的语句
发表于 2008-12-24 10:56:18 | 显示全部楼层
发表于 2008-12-24 12:13:18 | 显示全部楼层

好!顶!

好!不错。
发表于 2009-1-10 20:46:25 | 显示全部楼层
楼主太专业了,谢谢,值得研究研究!
发表于 2010-8-12 21:10:41 | 显示全部楼层
经验之谈,宝贵。。
发表于 2010-10-14 10:15:03 | 显示全部楼层
好东西,知道了哦
发表于 2012-11-14 09:12:07 | 显示全部楼层
回复 点赞 拍砖

使用道具 举报

发表于 2012-11-14 09:44:18 | 显示全部楼层
回复 点赞 拍砖

使用道具 举报

发表于 2012-11-18 15:30:01 | 显示全部楼层
回复 点赞 拍砖

使用道具 举报

头像被屏蔽
发表于 2012-12-4 09:51:08 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复 点赞 拍砖

使用道具 举报

发表于 2012-12-7 13:21:43 | 显示全部楼层
回复 点赞 拍砖

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号

本版积分规则

QQ|站长微信|Archiver|手机版|小黑屋|用友之家 ( 蜀ICP备07505338号|51072502110008 )

GMT+8, 2024-5-10 12:14 , Processed in 0.027030 second(s), 9 queries , Gzip On, Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表