SQL性能优化调整的几点基础事项_oracle

来源:互联网 发布:java 类命名规范 编辑:程序博客网 时间:2024/06/05 15:04

1.  选择最有效率的表名顺序
  SQL的解析器按照从右到左的顺序处理FROM子句中的表名, FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。
 
例如: 
    表 TAB1 16,384条记录    表 TAB2  1条记录
     选择TAB2作为基础表 (最好的方法):
     select count(*) from tab1,tab2   ----执行时间0.96秒
     选择TAB1作为基础表 (不佳的方法):
     select count(*) from tab2,tab1   ----执行时间26.09秒

 

 

2.  3个以上的表连接查询
  如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表。

例如: 
EMP表描述了LOCATION表和CATEGORY表的交集
  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

 

3.  WHERE子句中的连接顺序

  ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.

例如:
 (低效,执行时间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’;

 

4.  使用oracle自带函数提高效率
使用DECODE函数来减少处理时间,可以避免重复扫描相同记录或重复连接相同的表.

例如:
   SELECT COUNT(*),SUM(SAL)
   FROM EMP
   WHERE DEPT_NO = 0020
   AND ENAME LIKE ‘SMITH%’;
   SELECT COUNT(*),SUM(SAL)
   FROM EMP
   WHERE DEPT_NO = 0030
   AND ENAME LIKE ‘SMITH%’;

你可以用DECODE函数高效地得到相同结果:
SELECT COUNT(DECODE(DEPT_NO,0020,’X’,NULL)) D0020_COUNT,
        COUNT(DECODE(DEPT_NO,0030,’X’,NULL)) D0030_COUNT,
        SUM(DECODE(DEPT_NO,0020,SAL,NULL)) D0020_SAL,
        SUM(DECODE(DEPT_NO,0030,SAL,NULL)) D0030_SAL
FROM EMP WHERE ENAME LIKE ‘SMITH%’;

 

5.  用Where子句替换HAVING子句
  避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销。

  HAVING 中的条件一般用于对一些集合函数的比较,如COUNT() 等等. 除此而外,一般的条件应该写在WHERE子句中

 

6.  使用表的别名(Alias)
  当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.
  Column歧义指的是由于SQL中不同的表具有相同的Column名,当SQL语句中出现这个Column时,SQL解析器无法判断这个Column的归属.

 

7.  用表连接替换EXISTS
SELECT ENAME
FROM EMP E
WHERE EXISTS (SELECT ‘X’
  FROM DEPT
  WHERE DEPT_NO = E.DEPT_NO
 AND
DEPT_CAT = ‘A’);

(更高效的方法)
 SELECT ENAME
 FROM DEPT D,
  EMP E
WHERE
E.DEPT_NO = D.DEPT_NO
AND
DEPT_CAT = ‘A’ ;

 

8.  识别’低效执行’的SQL语句
使用TKPROF 工具来查询SQL性能状态
     SQL trace 工具收集正在执行的SQL的性能状态数据并记录到一个跟踪文件中. 这个跟踪文件提供了许多有用的信息,例如解析次数.执行次数,CPU使用时间等.这些数据将可以用来优化你的系统。
EXPLAIN PLAN 分析SQL语句:
     EXPLAIN PLAN 是一个很好的分析SQL语句的工具,它甚至可以在不执行SQL的情况下分析语句. 通过分析,我们就可以知道ORACLE是怎么样连接表,使用什么方式扫描表(索引扫描或全表扫描)以及使用到的索引名称。

 

9.  用索引提高效率
  索引是表的一个概念部分,用来提高检索数据的效率. 实际上,ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当ORACLE找出执行查询和Update语句的最佳路径时, ORACLE优化器将使用索引. 同样在联结多个表时使用索引也可以提高效率. 另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证.


  虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价. 索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改. 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出4 , 5 次的磁盘I/O . 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.

 

10.  用>=替代>
  两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录
例如:
高效:
   SELECT *
   FROM EMP
   WHERE DEPTNO  >=4

低效:
   SELECT *
   FROM EMP
   WHERE DEPTNO >3

 

11.  用UNION替换OR (适用于索引列)
  通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低
例如:
高效:
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”

 


 

原创粉丝点击