SQL优化技巧
1. 选择最有效率的表名顺序(只在基于规则的优化器中有效)
SQL 的解析器按照从右到左的顺序处理 FROM 子句中的表名,因此 FROM 子句中写在最后的表(我们称之为基础表)将被最先处理. 在 FROM 子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.当 SQL 处理多个表时, 会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM 子句中最后的那个表)并对记录进行派序,然后扫描第二个表
(FROM 子句中倒数第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记
录进行合并.
例如:
表 TAB1 16,384 条记录
表 TAB2 1 条记录
选择 TAB2 作为基础表 (最好的方法)
select count(*) from tab1,tab2执行时间 0.96 秒
选择 TAB2 作为基础表 (不佳的方法)
select count(*) from tab2,tab1 执行时间 26.09 秒
如果有 3 个以上的表连接查询, 那就需要选择交叉表作为基础表, 交叉表是指那个被其他
表所引用的表.
例如:
SC 表描述了 STUDENT 表和 COURCE 表的交集.
SELECT *
FROM STUDENT S ,
COURCE C,
SC
WHERE SC.SNO BETWEEN 95001 AND 95005
AND SC.CNO = C.CNO
AND SC.SNO = S.SNO
将比下列 SQL 更有效率
SELECT *
FROM SC
STUDENT S ,
COURCE C,
WHERE SC.CNO = C.CNO
AND SC.SNO = S.SNO
AND SC.SNO BETWEEN 95001 AND 95005
2 .WHERE 子句中的连接顺序.
SQL 采用自下而上的顺序解析 WHERE 子句,根据这个原理,表之间的连接必须写在其他 WHERE 条件之前, 那些可以过滤掉最大数量记录的条件必须写在 WHERE 子句的末尾.例如:
(低效,若 95%以上都大于十岁,一半人数男性,这样在先被执行的 student.sage 只排除了5%的数据)
SELECT …
FROM STUDENT
WHERE STUDENT.SSEX=’男’
STUDENT.SAGE>10
(高效,同上,先被执行的 student.ssex 可以直接排除 50%的数据,效率要高于上面写法)
SELECT …
FROM STUDENT
WHERE STUDENT.SAGE>10
AND STUDENT.SSEX=’男’
3 .SELECT 子句中避免使用 ‘ * ‘
当你想在 SELECT 子句中列出所有的行时,使用动态 SQL 列引用 ‘*’ 是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,SQL 在解析的过程中, 会将’*’ 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间.
4 .减少访问数据库的次数
当执行每条 SQL 语句时, ORACLE 在内部执行了许多工作: 解析 SQL 语句, 估算索引的利用率, 绑定变量 , 读数据块等等. 由此可见, 减少访问数据库的次数 , 就能实际上减少 SQL 的工作量.
如我们要做一次操作
效率最低的,将一次操作编程两条 SQL 语句
次低的,在一个 SQL 语句中定义变量、循环等等
高效率,只是使用 SELECT 基本语句
5. 用 TRUNCATE 替代 DELETE
当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有 COMMIT 事务,SQL 会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况)而当运用 TRUNCATE 时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短.
6 .计算记录条数时,如果可以通过索引检索 , 对索引列的计数仍旧是最快的 . 例如
COUNT(SNO)(sno 为索引列)
7 .用 Where 子句替换 HAVING 子句避免使用 HAVING 子句,
HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作.如果能通过 WHERE 子句限制记录的数目,那就能减少这方面的开销.(即如果能不用 having 就尽量不要使用 having,必要的情况如条件中有聚合函数,那就只把聚合函数的条件写进having)
8 .减少对表的查询
在含有子查询的 SQL 语句中,要特别注意减少对表的查询.即如果不用子查询就尽量少使用子查询,或一个 SQL 能 使用两次子查询就可以获得结果,如果用三次子查询就会调高消耗。
9 .通过内部函数提高 SQL 效率
同一个结果,如果使用了内部函数,效率要高于人为在 SQL 中进行计算。
10 .使用表的别名
当在 SQL 语句中连接多个表时, 请使用表的别名并把别名前缀于每个列上.这样一来,就可以减少解析的时间并减少那些由列歧义引起的语法错误.
11 .用 EXISTS 替代 IN
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况
下, 使用 EXISTS(或 NOTEXISTS)通常将提高查询的效率.