SQL语句优化规则
SQL语句优化规则
1) 尽量避免对索引列进行计算
例:
X WHERE sal*1.1>950
O WHERE sal>950/1.1
X WHERE SUBSTR(name,1,7)=’CAPITAL’
O WHERE name LIKE ‘CAPITAL%’
2) 比较值与索引列的数据类型一致
例:
emp_no: NUMBER型
O WHERE emp_no=123
X WHERE emp_no=’123’
emp_type:CHAR型
X WHERE emp_type=123 (此时,查询时,不利用索引列)
O WHERE emp_type=’123
3) 避免使用NULL
例:
X WHERE comm IS NOT NULL
X WHERE comm IS NULL
O WHERE comm>=0
4) 尽量避免使用NOT=(!=)
例:
X WHERE deptno!=0
O WHERE deptno>0
5) 对于复合索引,SQL语句必须使用主索引列
例:复合索引(deptno,job)
O WHERE deptno=20 AND job=’MANAGER’
O WHERE deptno=20
O WHERE job=’MANAGER’ AND deptno=20
X WHERE job=’MANAGER’
6) ORDER BY子句
例:
O 子句中,列的顺序与索引列的顺序一致。
O 子句中,列应为非空列。
7) 查询列与索引列次序(WHERE)一致
例:
O SELECT empno,job FROM emp
WHERE empno<100 AND job=’MANAGER’;
X SELECT empno,job FROM emp
WHERE job=’MANAGER’ AND empno<100;
8) 尽量少用嵌套查询
例:
X SELECT * FROM emp
WHERE empno IN (SELECT empno FROM OnWork);
O SELECT emp.* FROM emp t1,OnWork t2
WHERE t1.empno = t2.empno;
9) 多表连接时,使用表的别名来引用列。
例:
X SELECT ab02.aab001,ab01.aab004
FROM ab02 ,ab01
WHERE ab02.aab001 = ab01.aab001
O SELECT t1.aab004,t2.aab001
FROM ab02 t1,ab01 t2
WHERE t1.aab001=t2.aab001
10) 用NOT EXISTS代替NOT IN
例:
X SELECT * FROM ab01
WHERE aab001 NOT IN
(SELECT aab001 FROM ab02 WHERE aae140='3');
O SELECT * FROM ab01 t
WHERE NOT EXISTS
(SELECT 1 FROM ab02
WHERE aab001=t.aab001 AND aae140='3');
11) 用多表连接代替EXISTS子句
例:
X SELECT * FROM ab01 t
WHERE EXISTS
(SELECT 1 FROM ab02
WHERE aab001=t.aab001 AND aae140=‘3’);
O SELECT t1.* FROM ab01 t1,ab02 t2
WHERE t1.aab001 = t2.aab001 AND t2.aae140=‘3’;
12) 少用DISTINCT,用EXISTS代替
例:
X SELECT DISTINCT ac01.aac016 aac016 FROM ac01,ac02
WHERE ac01.aac001=ac02.aac001
AND ac01.aab001 = '100659‘
AND NVL(ac01.aac016,'0') <> '107'
AND NVL(ac01.aac008,'0') = '1'
AND ac02.aae140 = '3' AND ac02.aac031 = '1';
O SELECT aac016 FROM ac01 t
WHERE aab001 = '100659'
AND NVL(aac016,'0') <> '107'
AND NVL(aac008,'0') = '1'
AND EXISTS
(SELECT 1 FROM ac02 WHERE aac001=t.aac001
AND ac02.aae140 = '3' AND ac02.aac031 = '1');
13) 使用UNION ALL、MINUS、INTERSECT提高性能
14) 使用ROWID提高检索速度
对SELECT得到的单行记录,需进行DELETE、UPDATE操作时,使用ROWID将会使效率大大提高。
例:
SELECT rowid INTO v_rowid FROM t1
WHERE con1 FOR UPDATE OF col2;
……
UPDATE t1 SET col2=......
WHERE rowid=v_rowid;
15) 查询的WHERE过滤原则,应使过滤记录数最多的条件放在最前面。
例:
SELECT info
FROM taba a,tabb b,tabc c
WHERE a.acol between :alow and :ahigh
AND b.bcol between :blow and :bhigh
AND c.ccol between :clow and :chigh
AND a.key1 = b.key1
AND a.key2 = c.key2;
其中,A表的acol列可以最多减少查询的记录数目,其次为B表的bcol列,依次类推。
16) 尽量使用共享的SQL语句。
如经常使用select * from dept where deptno=值。如果每一个“值”都是常量,则每一次都会重新解释,不能共享内存中的SQL语句优化结果。
应把“值”设置为一个变量,所有的共同语句都可以优化一次,高度共享语句解释优化的结果。
例:
Select * from dept where deptno=:d;
17) 显式光标优于隐式光标
例:
隐式光标处理
UPDATE target
SET t_field = (SELECT s_information FROM source
WHERE source.key = target.key)
WHERE EXISTS (SELECT…FROM source
WHERE source.key = target.key)
不如下面的显式光标语句好:
显式光标处理:
DECLARE CURSOR c1 IS
SELECT * FROM source;
BEGIN
FOR row IN c1 LOOP
UPDATE target
SET t_field = row.s_information
WHERE key = row.key;
END LOOP;
END;
18) 规范程序书写,加快执行速度
Ø 尽量避免让DBMS进行强制类型转换工作;
Ø 尽量避免写隐式游标,写显式游标;
Ø 尽可能使用内嵌函数,避免不必要的开发;
Ø 常用功能提取成函数、过程来实现,避免额外的拷贝;
Ø 减少循环中不必要的代码,尤其是不能有SQL语句;
Ø 删除程序中没有使用的变量,删除永远不会执行的“死”代码,程序之间不传递不需要的额外的参数。