心语飘絮
别让今天的懒惰成为明天的遗憾!!!
 

1   环境

Oracle 8i or 9i

2   高效的sql语句

2.1                       Sql优化方法

RBO(rule-based optimizer)

CBO

2.1.1                          驱动表

12张行数不一致的表连接

      TAB1行数:16,384

      TAB2行数:1

×SELECT COUNT(*) FROM TAB2, TAB1;

SELECT COUNT(*) FROM TAB1, TAB2;

23张表连接

 ×SELECT *

    FROM EMP E,

       LOC L,

                CAT C

   WHERE  E.emp_no    BETWEEN 1000 AND 2000

     AND E.cat_no     = C.cat_no

     AND E.locn = L.locn;

SELECT *

    FROM LOC L,

               CAT C,

               EMP E

   WHERE E.emp_no      BETWEEN 1000 AND 2000

            AND E.cat_no       = C.cat_no

                      AND E.locn       = L.locn;

2.1.2                          Where语句顺序的效率

1)    使用索引引起的where语句效率

使用AND语句时行数多的放在前面

×SELECT *

    FROM emp E

   WHERE emp_sal > 50000

     AND emp_type = 'MANAGER'

     AND 25       < (SELECT COUNT(*) FROM EMP WHERE emp_mgr = E.emp_no);

SELECT *

    FROM emp E

   WHERE   25       < (SELECT COUNT(*) FROM EMP WHERE

emp_mgr = E.emp_no)

                    AND emp_sal > 50000

                             AND emp_type = 'MANAGER';

使用OR语句时,行数多的放在后面

×SELECT *

    FROM emp E

   WHERE 25       < (SELECT COUNT(*) FROM EMP WHERE emp_mgr = E.emp_no)

      OR (emp_sal > 50000

     AND emp_type = 'MANAGER');

SELECT *

    FROM emp E

   WHERE (emp_sal > 50000

     AND emp_type = 'MANAGER')

              OR 25       < (SELECT COUNT(*) FROM EMP WHERE emp_mgr = E.emp_no);

2ROWID的使用

      使用ROWIDWHERE语句效率最高。

 SELECT ROWID, ...

 INTO :emp_rowid, ...

 FROM emp

 WHERE emp.emp_no = 56722

   FOR UPDATE;

UPDATE emp

   SET emp.name = ... ,

 WHERE ROWID = :emp_rowid;

    3)减少访问次数

×SELECT emp_name, sal, grade

    FROM emp

   WHERE emp_no = 0342;

SELECT emp_name, sal, grade

    FROM emp

   WHERE emp_no = 0291;

SELECT A.emp_name, A.sal, A.grade,

                B.emp_name, B.sal, B.grade

    FROM emp A, emp B

   WHERE A.emp_no = 0342

                                  AND B.emp_no = 0291;

4Where语句的索引的使用

      1SUBSTR

×SELECT acc_name, trans_date, amount

        FROM transaction

       WHERE SUBSTR(account_name,1,7) = 'CAPITAL';

 


    SELECT acc_name, trans_date, amount

        FROM transaction

       WHERE account_name LIKE 'CAPITAL%';

      2)!=

 ×SELECT acc_name, trans_date, amount

        FROM transaction

       WHERE amount != 0;

 


  ○SELECT acc_name, trans_date, amount

            FROM transaction

                      WHERE amount > 0;

       3TRUNC

×SELECT acc_name, trans_date, amount

        FROM transaction

        WHERE TRUNC(trans_date) = TRUNC(SYSDATE);

 ○SELECT acc_name, trans_date, amount

        FROM transaction

        WHERE trans_date

 BETWEEN TRUNC(SYSDATE)

               AND TRUNC(SYSDATE) + .99999;

         4||

×SELECT acc_name, trans_date, amount

        FROM transaction

       WHERE acc_name || acc_type = 'AMEXA';

             

    SELECT acc_name, trans_date, amount

        FROM transaction

       WHERE acc_name = 'AMEX'

                                     AND acc_type = 'A';

 5)运算

×SELECT acc_name, trans_date, amount

        FROM transaction

        WHERE amount + 3000 < 5000;

             

    SELECT acc_name, trans_date, amount

        FROM transaction

                  WHERE amount < 5000 - 3000;

2.2                       SQL命令的使用秘诀

2.2.1                          DECODE的使用

×SELECT COUNT(*), SUM(salary)

    FROM emp

    WHERE dept_no = 0020

     AND emp_name LIKE 'SMITH%';

SELECT COUNT(*), SUM(salary)

    FROM emp

   WHERE dept_no = 0030

                  AND emp_name LIKE 'SMITH%';

SELECT COUNTDECODE(dept_no, 0020, 'X', NULL)) D0020_count,

        COUNT (DECODE(dept_no, 0030, 'X', NULL)) D0030_count,

           SUM (DECODE(dept,    0020, salary, NULL)) D0020_sal,

           SUM (DECODE(dept,    0030, salary, NULL)) D0030_sal

           FROM emp

                           WHERE emp_name LIKE 'SMITH%';

2.2.2                          表的别名的使用

×SELECT E.emp_no, name, tax_no, C.comp_code, comp_name

    FROM company C, emp E

   WHERE E.comp_code = C.comp_code;

SELECT E.emp_no, E.name, E.tax_no, C.comp_code, C.comp_name

     FROM company C,   emp E

     WHERE E.comp_code = C.comp_code;

2.2.3                          去掉重复行

DELETE FROM emp E

 WHERE E.rowid > ( SELECT MIN(X.rowid)

                     FROM emp X

                    WHERE X.emp_no = E.emp_no );

2.2.4                          表的行计数

SELECT COUNT(有索引的列) FROM TRANS;

SELECT COUNT(*) FROM TRANS;

SELECT COUNT(1) FROM TRANS;

2.2.5                          WHERE语句替换HAVING语句的使用

×SELECT region, AVG(loc_size)

    FROM location

   GROUP BY region

 HAVING region != 'SYDNEY'

              AND region != 'PERTH';

SELECT region, AVG(loc_size)

    FROM location

 WHERE region != 'SYDNEY'

    AND region != 'PERTH';

   GROUP BY region

2.2.6                          使用表连接替代EXISTS使用

×SELECT emp_name

    FROM emp

  WHERE (emp_cat, sal_range) =

         (SELECT MAX(category), MAX(sal_range) FROM emp_categories)

     AND emp_dept = 0020;

SELECT emp_name

    FROM emp

  WHERE emp_cat = (SELECT MAX(category) FROM emp_categories)

     AND sal_range = (SELECT MAX(sal_range) FROM emp_categories)

                   AND emp_dept = 0020;

2.2.7                          使用EXISTS替代表连接

×SELECT ...

    FROM dept D, emp E

 WHERE E.dept_no = D.dept_no

     AND E.emp_type = 'MANAGER'

         AND D.dept_cat = 'A';

SELECT ...

    FROM emp E

   WHERE EXISTS ( SELECT 'X'FROM dept

WHERE dept_no = E.dept_no

   AND dept_cat = 'A')

     AND E.emp_type = 'MANAGER';

×SELECT ...

    FROM dept D, emp E

WHERE E.dept_no = D.dept_no

     AND (E.emp_type = 'MANAGER'

      OR D.dept_cat = 'A');

SELECT ...

    FROM emp E

   WHERE E.emp_type = 'MANAGER';

OR EXISTS ( SELECT 'X'

 FROM dept

 WHERE dept_no = E.dept_no

   AND dept_cat = 'A');

2.2.8                          使用EXISTS代替DISTINCT语句

×SELECT DISTINCT dept_no, dept_name

    FROM dept D, emp E

     WHERE D.dept_no = E.dept_no;

SELECT dept_no, dept_name

    FROM dept D

   WHERE EXISTS ( SELECT 'X'

                    FROM emp E

                              WHERE E.dept_no = D.dept_no);

2.2.9                          使用NOT EXISTS代替NOT IN语句

×SELECT ...

     FROM emp

WHERE dept_no NOT IN ( SELECT dept_no

                          FROM dept

                                      WHERE dept_cat = 'A');

SELECT ...

    FROM emp E

   WHERE NOT EXISTS ( SELECT 'X'

                  FROM dept

                              WHERE dept_no = E.dept_no

AND dept_cat = 'A');

2.2.10                    使用union all 代替union 语句

Union        -------- 进行排序

Union All   -------- 不排序

2.2.11                    使用UnionIN代替OR语句

Loc_no, region上有索引

×SELECT ...

     FROM location

   WHERE loc_id = 10

      OR region = 'MELBOURNE';

SELECT ...

    FROM location

 WHERE loc_id = 10

UNION ALL

SELECT ...

    FROM location

   WHERE region = 'MELBOURNE';

×SELECT ...

    FROM location

   WHERE loc_id = 10

 OR loc_id = 20

      OR loc_id = 30;

SELECT ...

   FROM location

   WHERE loc_id IN (10, 20, 30);

3   高效索引

3.1                       索引的使用

使用索引时,要考虑以下因素:

1)索引列的计算

2)索引列的增加

3)索引列不要用NOT

4)索引中空值的使用

IS NULL, IS NOT NULL

5)索引列的数据类型的变换

EMP_TYPEvarchar2类型,下列语句使用索引

SELECT ...

 FROM emp

 WHERE emp_type = 123;

SELECT ...

   FROM emp

 WHERE TO_NUMBER(emp_type) = 123;

SELECT ...

 FROM emp

 WHERE emp_type = '123';

3.2                       增加索引

增加索引要考虑多种因素,要考虑对更新、插入的影响等。

1)频繁查询不超过大表1%~15%的场合。

2)列的不同值

3)

4)

5)同表

4   解析表的使用方法

4.1                       SQLTRACE

4.1.1                          参数表的生成

$>sqlplus –s /

SQL>@$ORACLE_HOME/rdbms/admin/utlxplan.sql

SQL> commit

SQL> exit

4.1.2                          AUTOTRACE的用法

@afe57gc2/users/home/ino 29 >sqlplus sys/****

SQL> @$ORACLE_HOME/sqlplus/admin/plustrce.sql

SQL> drop role plustrace;

    :

SQL> grant plustrace to ops$ino;

SQL> exit

4.1.3                          AUTOTRACE功能的使用

@afe57gc2/oracle/product/8.1.7 37 >sqlplus /

SQL> set autotrace on

SQL> select * from wcattori;

执行计划

----------------------------------------------------------

            0      SELECT STATEMENT Optimizer=CHOOSE

   1    0   TABLE ACCESS (FULL) OF 'WCATTORI'

統計

----------------------------------------------------------

          0 recursive calls

         12 db block gets

          4 consistent gets

          0 physical reads

          0 redo size

       4779 bytes sent via SQL*Net to client

        314 bytes received via SQL*Net from client

          1 SQL*Net roundtrips to/from client

          0 sorts (memory)

          0 sorts (disk)

          0 rows processed

           SQL>

4.2                       TKPROF

4.2.1                          初始化

@afe57gc2/oracle/product/8.1.7 40 >sqlplus /

SQL> ALTER SESSION SET TIMED_STATISTICS = true;

SQL> ALTER SESSION SET MAX_DUMP_FILE_SIZE = 500;

4.2.2                          SQL Trace开始

SQL> ALTER SESSION SET SQL_TRACE = true;

4.2.3                          实例

SQL> SELECT * FROM WCATTORI;

4.2.4                          SQL Trace结束

SQL> ALTER SESSION SET SQL_TRACE = false;

SQL> exit

4.2.5                          内容变换

@afe57gc2/users/home/ino 44 >su

Password:

# chmod 777 /oracle/product/8.1.7/rdbms/log/ora_14186_wca1.trc

# exit

@afe57gc2/users/home/ino 46 >tkprof $ORACLE_HOME/rdbms/log/ora_14186_wca1.trc output.txt

TKPROF: Release 8.1.7.2.0 - Production on Apr 18 15:55:17 2002

(c) Copyright 2000 Oracle Corporation. All rights reserved.

備考:ログファイルの出力先

SQL> column name format A20

SQL> column value format A30

SQL> select name, value from v$parameter where name like '%dump_dest';

NAME                 VALUE

-------------------- ------------------------------

background_dump_dest ?/rdbms/log

user_dump_dest       ?/rdbms/log

core_dump_dest       ?/dbs

SQL>

4.2.6                          内容确认

@afe57gc2/users/home/ino 47 >cat output.txt (一部抜粋)

SELECT *

FROM

 WCATTORI

call     count       cpu    elapsed       disk      query    current        rows

------- ------ -------- ---------- ---------- ---------- ---------- ----------

Parse        1      0.00       0.00          0          0          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        1      0.00       0.00          0          4         12           0

------- ------ -------- ---------- ---------- ---------- ---------- ----------

total        3      0.00       0.00          0          4         12           0

Misses in library cache during parse: 0

Optimizer goal: CHOOSE

Parsing user id: 34

Rows     Row Source Operation

------- ---------------------------------------------------

      0 TABLE ACCESS FULL WCATTORI

posted on 2007-10-25 14:20  jeffery0101  阅读(1260)  评论(0编辑  收藏  举报