Vincent.Chan‘s Blog

          常用鏈接

          統計

          積分與排名

          網站

          最新評論

          ORACLE SQL性能優化系列 (十三)

          ORACLE SQL性能優化系列 (十三)

          作者: black_snail

           

          關鍵字 ORACLE PERFORMANCE TUNING PL/SQL

          出處 http://www.dbasupport.com



          43. 用WHERE替代ORDER BY

          ORDER BY 子句只在兩種嚴格的條件下使用索引.


          ORDER BY中所有的列必須包含在相同的索引中并保持在索引中的排列順序.

          ORDER BY中所有的列必須定義為非空.


          WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列.


          例如:

          表DEPT包含以下列:

          DEPT_CODE PK NOT NULL

          DEPT_DESC NOT NULL

          DEPT_TYPE NULL


          非唯一性的索引(DEPT_TYPE)


          低效: (索引不被使用)

          SELECT DEPT_CODE

          FROM DEPT

          ORDER BY DEPT_TYPE


          EXPLAIN PLAN:

          SORT ORDER BY

          TABLE ACCESS FULL


          高效: (使用索引)


          SELECT DEPT_CODE

          FROM DEPT

          WHERE DEPT_TYPE > 0


          EXPLAIN PLAN:

          TABLE ACCESS BY ROWID ON EMP

          INDEX RANGE SCAN ON DEPT_IDX

          譯者按:

          ORDER BY 也能使用索引! 這的確是個容易被忽視的知識點. 我們來驗證一下:

          SQL> select * from emp order by empno;

          Execution Plan

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

          0 SELECT STATEMENT Optimizer=CHOOSE

          1 0 TABLE ACCESS (BY INDEX ROWID) OF 'EMP'

          2 1 INDEX (FULL SCAN) OF 'EMPNO' (UNIQUE)



          44. 避免改變索引列的類型.

          當比較不同數據類型的數據時, ORACLE自動對列進行簡單的類型轉換.


          假設 EMPNO是一個數值類型的索引列.


          SELECT …

          FROM EMP

          WHERE EMPNO = ‘123'


          實際上,經過ORACLE類型轉換, 語句轉化為:

          SELECT …

          FROM EMP

          WHERE EMPNO = TO_NUMBER(‘123')


          幸運的是,類型轉換沒有發生在索引列上,索引的用途沒有被改變.


          現在,假設EMP_TYPE是一個字符類型的索引列.

          SELECT …

          FROM EMP

          WHERE EMP_TYPE = 123


          這個語句被ORACLE轉換為:

          SELECT …

          FROM EMP

          WHERE TO_NUMBER(EMP_TYPE)=123


          因為內部發生的類型轉換, 這個索引將不會被用到!

          譯者按:

          為了避免ORACLE對你的SQL進行隱式的類型轉換, 最好把類型轉換用顯式表現出來. 注意當字符和數值比較時, ORACLE會優先轉換數值類型到字符類型.



          45. 需要當心的WHERE子句

          某些SELECT 語句中的WHERE子句不使用索引. 這里有一些例子.

          在下面的例子里, ‘!=' 將不使用索引. 記住, 索引只能告訴你什么存在于表中, 而不能告訴你什么不存在于表中.

          不使用索引:

          SELECT ACCOUNT_NAME

          FROM TRANSACTION

          WHERE AMOUNT !=0;

          使用索引:

          SELECT ACCOUNT_NAME

          FROM TRANSACTION

          WHERE AMOUNT >0;


          下面的例子中, ‘||'是字符連接函數. 就象其他函數那樣, 停用了索引.

          不使用索引:

          SELECT ACCOUNT_NAME,AMOUNT

          FROM TRANSACTION

          WHERE ACCOUNT_NAME||ACCOUNT_TYPE='AMEXA';

          使用索引:

          SELECT ACCOUNT_NAME,AMOUNT

          FROM TRANSACTION

          WHERE ACCOUNT_NAME = ‘AMEX'

          AND ACCOUNT_TYPE=' A';


          下面的例子中, ‘+'是數學函數. 就象其他數學函數那樣, 停用了索引.

          不使用索引:

          SELECT ACCOUNT_NAME, AMOUNT

          FROM TRANSACTION

          WHERE AMOUNT + 3000 >5000;

          使用索引:

          SELECT ACCOUNT_NAME, AMOUNT

          FROM TRANSACTION

          WHERE AMOUNT > 2000 ;

          下面的例子中,相同的索引列不能互相比較,這將會啟用全表掃描.

          不使用索引:

          SELECT ACCOUNT_NAME, AMOUNT

          FROM TRANSACTION

          WHERE ACCOUNT_NAME = NVL(:ACC_NAME,ACCOUNT_NAME);

          使用索引:

          SELECT ACCOUNT_NAME, AMOUNT

          FROM TRANSACTION

          WHERE ACCOUNT_NAME LIKE NVL(:ACC_NAME,'%');


          譯者按:

          如果一定要對使用函數的列啟用索引, ORACLE新的功能: 基于函數的索引(Function-Based Index) 也許是一個較好的方案.

          CREATE INDEX EMP_I ON EMP (UPPER(ename)); /*建立基于函數的索引*/

          SELECT * FROM emp WHERE UPPER(ename) = ‘BLACKSNAIL'; /*將使用索引*/

          posted on 2006-02-25 22:34 Vincent.Chen 閱讀(189) 評論(0)  編輯  收藏 所屬分類: Database

          主站蜘蛛池模板: 石首市| 仲巴县| 铁力市| 景宁| 格尔木市| 沙坪坝区| 丹巴县| 十堰市| 武定县| 容城县| 林西县| 东兰县| 四川省| 江永县| 德昌县| 寿光市| 沾化县| 肥城市| 进贤县| 黔江区| 淄博市| 行唐县| 阿坝县| 平阳县| 灵石县| 金昌市| 鹿邑县| 沙湾县| 临澧县| 德清县| 华蓥市| 清苑县| 茶陵县| 习水县| 深州市| 安吉县| 垦利县| 宜黄县| 罗定市| 崇左市| 连州市|