SQL优化原则(五)

2014-11-24 12:24:56 · 作者: · 浏览: 2
E子句使用的索引和ORDER BY子句中所使用的索引不能并列.
例如:
表DEPT包含以下列:
DEPT_CODE PK NOT NULL
DEPT_DESC NOT NULL
DEPT_TYPE NULL
低效: (索引不被使用)
SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE
高效: (使用索引)
SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0
(30) 避免改变索引列的类型.:
当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换.
假设 EMPNO是一个数值类型的索引列.
SELECT … FROM EMP WHERE EMPNO = ‘123'
实际上,经过ORACLE类型转换, 语句转化为:
SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123')
幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变.
现在,假设EMP_TYPE是一个字符类型的索引列.
SELECT … FROM EMP WHERE EMP_TYPE = 123
这个语句被ORACLE转换为:
SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123
因为内部发生的类型转换, 这个索引将不会被用到! 为了避免ORACLE对你的SQL进行
隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE
会优先转换数值类型到字符类型
(31) 需要当心的WHERE子句:
某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子.
在下面的例子里, (1)‘!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告
诉你什么不存在于表中. (2) ‘ '是字符连接函数. 就象其他函数那样, 停用了索引. (3) ‘+'
是数学函数. 就象其他数学函数那样, 停用了索引. (4)相同的索引列不能互相比较,这将会启用全表扫描.
(32) a. 如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高.
b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常
情况下,使用索引比全表扫描要块几倍乃至几千倍!
(33) 避免使用耗费资源的操作:
带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎
执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行
两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写.
如果你的数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也
是可以考虑的, 毕竟它们的可读性很强
(34) 优化GROUP BY:
提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.
下面两个查询返回相同结果但第二个明显就快了许多.
低效:
SELECT JOB , AVG(SAL)
FROM EMP
GROUP by JOB
HAVING JOB = ‘PRESIDENT'
OR JOB = ‘MANAGER'
高效:
SELECT JOB , AVG(SAL)
FROM EMP
WHERE JOB = ‘PRESIDENT'
OR JOB = ‘MANAGER'
GROUP by JOB
====================================
====================================
如果你正在负责一个基于SQL Server的项目,或者你刚刚接触SQL Server,你都
有可能要面临一些数据库性能的问题,这篇文章会为你提供一些有用的指导(其中
大多数也可以用于其它的DBMS)。
在这里,我不打算介绍使用SQL Server的窍门,也不能提供一个包治百病的方案,
我所做的是总结一些经验----关于如何形成一个好的设计。这些经验来自我过去几年
中经受的教训,一直来,我看到许多同样的设计错误被一次又一次的重复。
一、了解你用的工具
不要轻视这一点,这是我在这篇文章中讲述的最关键的一条。也许你也看到有很多
的SQL Server程序员没有掌握全部的T-SQL命令和SQL Server提供的那些有用的工具。
“什么?我要浪费一个月的时间来学习那些我永远也不会用到的SQL命令???”,你
也许会这样说。对的,你不需要这样做。但是你应该用一个周末浏览所有的 T-SQL
命令。在这里,你的任务是了解,将来,当你设计一个查询时,你会记起来:“对了
,这里有一个命令可以完全实现我需要的功能”,于是,到MSDN 查看这个命令的确切语法。
二、不要使用游标
让我再重复一遍:不要使用游标。如果你想破坏整个系统的性能的话,它们倒是你
最有效的首选办法。大多数的初学者都使用游标,而没有意识到它们对性能造成
的影响。它们占用内存,还用它们那些不可思议的方式锁定表,另外,它们简
直就像蜗牛。而最糟糕的是,它们可以使你的DBA所能做的一切性能优化等于没
做。不 知你是否知道每执行一次FETCH就等于执行一次SELECT命令?这意味
着如果你的游标有10000条记录,它将执行10000次SELECT!如果你 使用一组
SELECT、UPDATE或者DELETE来完成相应的工作,那将有效率的多。
初学者一般认为使用游标是一种比较熟悉和舒适的编程方式,可很不幸,这会导致
糟糕的性能。显然,SQL的总体目的是你要实现什么,而不是怎样实现。
我曾经用T-SQL重写了一个基于游标的存储过程,那个表只有100,000条记录,原
来的存储过程用了40分钟才执行完毕,而新的存储过程只用了10秒钟。在这里,
我想你应该可以看到一个不称职的程序员究竟在干了什么!!!
我们可以写一个小程序来取得和处理数据并且更新数据库,这样做有时会更有效。
记住:对于循环,T-SQL无能为力。
我再重新提醒一下:使用游标没有好处。除了DBA的工作外,我从来没有看到过使
用游标可以有效的完成任何工作。
三、规范化你的数据表
为什么不规范化数据库?大概有两个借口:出于性能的考虑和纯粹因为懒惰。至于
第二点,你迟早得为此付出代价。而关于性能的问题,你不需要优化根本就不慢的
东西。我经常看到一些程序员“反规范化”数据库,他们的理由是“原来的设计太慢了”,
可结果却常常是他们让系统更慢了。DBMS被设计用来处理规范数据库 的,因此,
记住:按照规范化的要求设计数据库。
四、不要使用SELECT *
这点不太容易做到,我太了解了,因为我自己就经常这样干。可是,如果在SELECT
中指定你所需要的列,那将会带来以下的好处:
1 减少内存耗费和网络的带宽
2 你可以得到更安全的设计
3 给查询优化