1、选用适合的Oracle优化器
RULE(基于规则) COST(基于成本) CHOOSE(选择性)
2、增加索引
重构索引:
ALTER INDEX
避免在索引列上使用计算:
低效:
SELECT …
FROM DEPT
WHERE SAL * 12 > 25000;
高效:
SELECT …
FROM DEPT
WHERE SAL > 25000/12;
用 >= 替代 >:
低效:
SELECT *
FROM EMP
WHERE DEPTNO >3
高效:
SELECT *
FROM EMP
WHERE DEPTNO >=4
3、 共享 SQL 语句
4、选择最有效率的表名顺序
举例:
表 TAB1 有 9999 条记录
表 TAB2 有 1 条记录
PS:就是把数据多的作为基础表;交叉表作为基础表
/*选择TAB1作为基础表 (最好的方法)*/
select count(*) from tab1,tab2 执行时间0.96秒
/*选择TAB2作为基础表 (不佳的方法)*/
select count(*) from tab2,tab1 执行时间26.09秒
如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表。
SELECT * FROM LOCATION L, CATEGORY C, EMP E
WHERE E.EMP_NO BETWEEN 1000 AND 2000
AND E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
将比下列SQL更有效率
SELECT * FROM EMP E, LOCATION L, CATEGORY C
WHERE E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
AND E.EMP_NO BETWEEN 1000 AND 2000
5、Where子句中的连接顺序
Oracle采用自下而上的顺序解析WHERE子句。 根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
PS:能过滤数据量的条件往后边放
/*低效,执行时间156.3秒*/
SELECT …
FROM EMP E
WHERE SAL > 50000
AND JOB = ‘MANAGER’
AND 25 < (SELECT COUNT(*) FROM EMP
WHERE MGR = E.EMPNO)
/*高效,执行时间10.6秒*/
SELECT …
FROM EMP E
WHERE 25 < (SELECT COUNT(*) FROM EMP
WHERE MGR=E.EMPNO)
AND SAL > 50000
AND JOB = ‘MANAGER’
6、SELECT子句中避免使用 *
7、使用Truncate而非Delete
8、用Where子句替换Having子句
避免使用HAVING子句,HAVING 只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序、总计等操作。 如果能通过WHERE子句限制记录的数目,就能减少这方面的开销。
9、减少对表的查询操作
在含有子查询的SQL语句中,要注意减少对表的查询操作。
低效:
SELECT TAB_NAME FROM TABLES
WHERE TAB_NAME =(SELECT TAB_NAME
FROM TAB_COLUMNS
WHERE VERSION = 604)
AND DB_VER =(SELECT DB_VER
FROM TAB_COLUMNS
WHERE VERSION = 604)
高效:
SELECT TAB_NAME FROM TABLES
WHERE (TAB_NAME,DB_VER)=
(SELECT TAB_NAME,DB_VER
FROM TAB_COLUMNS
WHERE VERSION = 604)
10、 使用表的别名(Alias)
当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误。
11、用EXISTS替代IN
12、用NOT EXISTS替代NOT IN
13、用IN替换OR
在实际项目中,尽量少用 IN ,能用循环解决的别用 IN 。循环比 IN 的效率高很多很多。
14、 使用UNION ALL替代UNION
当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并,然后在输出最终结果前进行排序。如果用UNION ALL替代UNION,这样排序就不是必要了,效率就会因此得到提高。
由于UNION ALL的结果没有经过排序,而且不过滤重复的记录,因此是否进行替换需要根据业务需求而定。
15、几种不能使用索引的WHERE子句
(1)、‘!=’ 将不使用索引
(2)、使用了数学函数
低效:WHERE AMOUNT + 3000 >5000;
高效:WHERE AMOUNT >2000;
(3)、相同的索引列不能互相比较
16、避免使用耗费资源的操作
17. 使用显示游标(CURSORS)
使用隐式的游标,将会执行两次操作。第一次检索记录,第二次检查TOO MANY ROWS 这个exception。而显式游标不执行第二次操作。
18. 分离表和索引