登陆论坛 找回密码 立刻获得20pp! 地图 帮助
宽带山生活
版主:

  • 主题内容
<< [1] >>  [只看楼主]  [加入关注] 点击:343 回复:4 已被0人关注

主题:SQL语句的编写原则和SQL语句的优化(收集文档,写得不错

330 0

来自:上海
注册:2003-01-06
发帖:146+2195 
在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于大量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统不是简单地能实现其功能就可,而是要写出高质量的SQL语句,提高系统的可用性。

在多数情况下,Oracle使用索引来更快地遍历表,优化器主要根据定义的索引来提高性能。但是,如果在SQL语句的where子句中写的SQL代码不合理,就会造成优化器删去索引而使用全表扫描,一般就这种SQL语句就是所谓的劣质SQL语句。在编写SQL语句时我们应清楚优化器根据何种原则来使用索引,这有助于写出高性能的SQL语句。

SQL语句的编写原则和SQL语句的优化:

●选择一个好的表联接顺序(这是一个比较重要的原则)

当在WHERE子句中有多个表联接时,WHERE子句中排在最后的表应当是返回行数可能最少的表,有过滤条件的子句应放在WHERE子句中的最后。

如:设从emp表查到的数据比较少或该表的过滤条件比较确定,能大大缩小查询范围,则将最具有选择性部分放在WHERE子句中的最后:

select * from emp e,dept d where d.deptno >10 and e.deptno =30 ;

如果dept表返回的记录数较多的话,上面的查询语句会比下面的查询语句响应快得多。

select * from emp e,dept d where e.deptno =30 and d.deptno >10 ;

●最好不要在WHERE子句中使用函或表达式,如果要使用的话,最好统一使用相同的表达式或函数,这样便于以后使用合理的索引。

● 同一个SQL子句应该尽可能简单,将复杂的SQL 子句改写为简单的SQL子句。

● 使用WHERE (NOT)EXISTS 来代替(NOT)IN子句,使用NOT EXISTS 子句可以有效地利用索引。

尽可能使用NOT EXISTS来代替NOT IN,尽管二者都使用了NOT(不能使用索引而降低速度),NOT EXISTS要比NOT IN查询效率更高。

例子:

语句1

SELECT dname, deptno FROM dept WHERE deptno NOT IN (SELECT deptno FROM emp);

语句2

SELECT dname, deptno FROM dept WHERE NOT EXISTS (SELECT deptno FROM emp WHERE dept.deptno = emp.deptno);

明显的,2要比1的执行性能好很多。

因为1中对emp进行了full table scan,这是很浪费时间的操作。而且1中没有用到emp的index, 因为没有where子句。而2中的语句对emp进行的是缩小范围的查询。

● 通过使用>=、<=等,避免使用NOT命令。

如这个例子:

select * from employee where salary<>3000;

对这个查询,可以改写为不使用NOT:

select * from employee where salary<3000 or salary>3000;

虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。

● 如果有其它办法,不要使用子查询。

●外部联接"+"的用法

---- 外部联接"+"按其在"="的左边或右边分左联接和右联接。若不带"+"运算符的表中的一个行不直接匹配于带"+"预算符的表中的任何行,则前者的行与后者中的一个空行相匹配并被返回。利用外部联接"+",可以替代效率十分低下的 not in 运算,大大提高运行速度。例如,下面这条命令执行起来很慢:

select a.empno from emp a where a.empno not in

(select empno from emp1 where job='SALE');

---- 倘若利用外部联接,改写命令如下:

select a.empno from emp a ,emp1 b

where a.empno=b.empno(+)

and b.empno is null

and b.job='SALE';

这样运行速度明显提高.

-●在查询时尽量少用格式转换。

如用 WHERE a.order_no = b.order_no

而不用

WHERE TO_NUMBER (substr(a.order_no, instr(b.order_no, '.') - 1)

= TO_NUMBER (substr(a.order_no, instr(b.order_no, '.') - 1)

-●Order by语句

ORDER BY语句决定了Oracle如何将返回的查询结果排序。Order by语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)。任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。

仔细检查order by语句以找出非索引项或者表达式,它们会降低性能。解决这个问题的办法就是重写order by语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在order by子句中使用表达式。

-●IS NULL 与 IS NOT NULL

不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。

任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。

●SQL语句各部分的格式

一条语句可以一行也可以分多行书写,但最好换行书写,每一子句一行,且每行的第一个关键字与第一行的关键字的尾部对齐,这样做以确保每次使用同一条语句时分行的位置一致。



-------------------------------------------------------------------------------------------
这个家伙很懒,什么也没留下......

发表于:2003-08-11 17:07:28

158

来自:北京
注册:2002-07-11
发帖:71+279 
eway兄在,快来帮我看看下面的问题~~~~downloading



-------------------------------------------------------------------------------------------
不好意思呦~~我是个菜鸟=^______^=


妖兽工厂


http://asp.7i24.com/ericbj/

发表于:2003-08-11 17:11:40

pcdog@面试
958 1

来自:上海
注册:2000-10-03
发帖:820+13373 
你下面有什么问题阿




-------------------------------------------------------------------------------------------
打击正版,支持盗版

http://www.shtvu.com

发表于:2003-08-11 18:46:16

370 0

来自:保密
注册:2000-12-20
发帖:60+112 
downloading



-------------------------------------------------------------------------------------------
超级潜水艇:P

发表于:2003-08-24 12:52:01
推荐:视康全功能360ML+镜盒,免费抽 ...第3楼...

回复主题 [ 返回ASP ]
主题: SQL语句的编写原则和SQL语句的优化(收集文档,写得不错
手机看宽带山

关于我们 - 联系我们 - 加入我们 - 营销服务 - 友情链接 - 频道合作- PChome Widget
Copyright © 1996-2009 PChome.net All rights reserved. 电脑之家 版权所有