Sql 优化:
当Oracle数据库拿到SQL语句时,其会根据查询优化器分析该语句,并根据分析结果生成查询执行计划。
也就是说,数据库是执行的查询计划,而不是Sql语句。
查询优化器有rule-based-optimizer(基于规则的查询优化器) 和Cost-Based-optimizer(基于成本的查询优化器)。
其中基于规则的查询优化器在10g版本中消失。
对于规则查询,其最后查询的是全表扫描。而CBO则会根据统计信息进行最后的选择。
1、先执行From ->Where ->Group By->Order By
2、执行From 字句是从右往左进行执行。因此必须选择记录条数最少的表放在右边。这是为什么呢?
3、对于Where字句其执行顺序是从后向前执行、因此可以过滤最大数量记录的条件必须写在Where子句的末尾,而对于多表之间的连接,则写在之前。
因为这样进行连接时,可以去掉大多不重复的项。
5、索引失效的情况:
① Not Null/Null 如果某列建立索引,当进行Select * from emp where depto is not null/is null。 则会是索引失效。
② 索引列上不要使用函数,SELECT Col FROM tbl WHERE substr(name ,1 ,3 ) = ‘ABC’
或者SELECT Col FROM tbl WHERE name LIKE ‘%ABC%’ 而SELECT Col FROM tbl WHERE name LIKE ‘ABC%’ 会使用索引。
③ 索引列上不能进行计算SELECT Col FROM tbl WHERE col / 10 > 10 则会使索引失效,应该改成
SELECT Col FROM tbl WHERE col > 10 * 10
④ 索引列上不要使用NOT ( != 、 <> )如:SELECT Col FROM tbl WHERE col ! = 10
应该 改成:SELECT Col FROM tbl WHERE col > 10 OR col < 10 。
6、用UNION替换OR(适用于索引列)
union:是将两个查询的结果集进行追加在一起,它不会引起列的变化。 由于是追加操作,需要两个结果集的列数应该是相关的,
并且相应列的数据类型也应该相当的。union 返回两个结果集,同时将两个结果集重复的项进行消除。 如果不进行消除,用UNOIN ALL.
通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效.
如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引.
高效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10
UNION
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE REGION = “MELBOURNE”
低效:
SELECT LOC_ID , LOC_DESC , REGION
FROM LOCATION
WHERE LOC_ID = 10 OR REGION = “MELBOURNE”
//如果你坚持要用OR, 那就需要返回记录最少的索引列写在最前面.
例子:
高效:
SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’ FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB’)
低效:
SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB’)
8,优化GROUP BY:
提高GROUP BY 语句的效率,可以通过将不需要的记录在GROUP BY之前过滤掉。
下面两个查询返回相同结果但明显第二个效率更高。
低效:
SELECT JOB,AVG(AGE) FROM TEMP
GROUP BY JOB HAVING JOB = 'STUDENT' OR JOB = 'MANAGER';
高效:
SELECT JOB,AVG(AGE) FROM EMP
WHERE JOB = 'STUDENT' OR JOB = 'MANAGER' GROUP BY JOB;
9、删除重复记录:
DELETE FROM music m WHERE ROWID >
(SELECT MIN(ROWID) FROM music u WHERE u.music_id = m.music_id)//(有待测试)