SQL优化

 

1.   SELECT子句中避免使用 ‘ * ‘

结论:

Select * from table 会通过查询数据字典完成所有Column的转换。

 

2.   Truncate Table & Delete Table.

结论:

当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果全表删除,用TRUNCATE时, 回滚段不再存放任何可被恢复的信息,因此很少的资源被调用,执行时间也会很短

 

3.   多表查询时的别名

结论:

减少解析的时间并减少那些由字段歧义引起的语法错误

 

4.   用EXISTS替代IN,用NOT EXISTS替代NOT IN;采用表连接的方式比EXISTS更有效率

 

低效:

SELECT *

FROM EMP

WHERE EMPNO > 0

AND DEPTNO IN (SELECT DEPTNO

FROM DEPT

WHERE LOC = 'MELB')

   

高效:

SELECT *

FROM EMP

WHERE EMPNO > 0

AND EXISTS (SELECT 'X'

FROM DEPT

WHERE DEPT.DEPTNO = EMP.DEPTNO

AND LOC = 'MELB')

 

5.   用表连接替换EXISTS

/* 低效 */

SELECT LN.*

 FROM edi_ord_ln LN

 WHERE EXISTS (SELECT rodorderno

                 FROM edi_ord_hd

                WHERE rodorderno = LN.rodorderno);

 

/* 高效*/

SELECT LN.*

 FROM edi_ord_ln LN, edi_ord_hd hd

 WHERE LN.rodorderno = hd.rodorderno;

 

结论:在RBO的情况下,前者的执行路径包括FILTER,后者使用NESTED LOOP

 

6.   尽量多使用COMMIT

Commit可以释放用于(1)恢复回滚段上的数据信息(2)被程序语句获得的锁(3redo log buffer中的空间

在使用COMMIT时必须要注意到事务的完整性

 

7.   Where中数据转换函数及公式放右边

SELECT *

 FROM tibcoeai.sap_so_hd saphd, edi_ord_ln LN

 WHERE saphd.zzrods =;

 

SELECT *

 FROM tibcoeai.sap_so_hd saphd, edi_ord_ln LN

 WHERE TO_CHAR (LN.rodorderno) = saphd.zzrods;

 

select * from edi_ord_ln where orderqty*10>100;

select * from edi_ord_ln where orderqty> 100/10;

 

8.   等式和比较范围

select * from edi_ord_ln

where

MFGSITE='WCZ521'

and orderqty >2;

 

select * from edi_ord_ln

where

orderqty >2

and MFGSITE='WCZ521';

 

9.   >=和>比较

低效:

select * from edi_ord_ln

where

orderqty >2;

 

高效:

select * from edi_ord_ln

where

orderqty >=3;

结论:

前者DBMS先定位到OrderQty=2记录,然后再向前扫描第一个OrderQty>2的记录。

后者,DBMS直接跑到OrderQty=3的记录。

 

10. 避免索引列使用 != 和|| 操作

!=会引起全表检索。

索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中.

 

11. SQL的书写顺序(Based on Rule)

From子句是按从右到左的顺序执行如果有3个以上的表连接查询,那就需要选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表。从效率上讲,小表应该作外表(驱动表),大表应该作内表,即大表查询时走索引。即驱动表(Driving table, 通常以全表扫描的方式被访问)放最右边。

注意:如果一个表有索引,一个表没有索引,ORACLE会将没有索引的表作驱动表。如果两个表都有索引,则外表作驱动表。如果两个都没索引的话,则也是外表作驱动表。

   Where子句是按从下到上的顺序执行,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾

SELECT LN.cancelledflag, LN.unitprice

FROM edi_ord_hd hd, edi_ord_ln LN

 WHERE hd.rodorderno = LN.rodorderno

   AND LN.ctoitem = 'Y'

   AND hd.customer = '200383'

 

 

 

12. 存储过程中需要用到连接多个表时尽量采用oracle语法,避免pl/sql语法

/* Formatted on 2009/11/19 08:56 (Formatter Plus v4.8.7) */

SELECT SUM (CASE

               WHEN LN.cancelledflag = 'N'

                  THEN (LN.orderqty * LN.unitprice)

               ELSE 0

            END

           ) AS total

 FROM edi_ord_hd hd LEFT JOIN edi_ord_ln LN

       ON hd.rodorderno = LN.rodorderno

     AND hd.customer = '200383'

     AND LN.ctoitem = 'Y';

 

/* Formatted on 2009/11/19 09:00 (Formatter Plus v4.8.7) */

SELECT SUM (DECODE (LN.cancelledflag, 'N', LN.orderqty * LN.unitprice, 0)

           ) AS total

 FROM edi_ord_hd hd, edi_ord_ln LN

 WHERE hd.rodorderno(+) = LN.rodorderno AND hd.customer = '200383'

       AND LN.ctoitem = 'Y';

Explain Tool Compare:

结论:

(1)避免oracle将left join再重新解析;

(2)使用decode比使用case的效率要高,使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表;

 

10. 减少对表的查询

低效:

          UPDATE EMP

          SET EMP_CAT = (SELECT MAX(CATEGORY) FROM EMP_CATEGORIES),

              SAL_RANGE = (SELECT MAX(SAL_RANGE) FROM EMP_CATEGORIES)

          WHERE EMP_DEPT = 0020;

高效:

          UPDATE EMP

          SET (EMP_CAT, SAL_RANGE) = (SELECT MAX(CATEGORY) , MAX(SAL_RANGE)

FROM EMP_CATEGORIES)

          WHERE EMP_DEPT = 0020;

 

低效:

          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)

 

 

11.通过内部函数提高SQL效率.

 

posted @ 2009-11-20 14:21  vincent shi  阅读(273)  评论(0编辑  收藏  举报