什麼是執行計劃
所謂執行計劃,顧名思義,就是對一個查詢任務,做出一份怎樣去完成任務的詳細方案。舉個生活中的例子,我從珠海要去英國,我可以選擇先去香港然後轉機,也可以先去北京轉機,或者去廣州也可以。但是到底怎樣去英國劃算,也就是我的費用最少,這是一件值得考究的事情。同樣對於查詢而言,我們提交的SQL僅僅是描述出了我們的目的地是英國,但至於怎麼去,通常我們的SQL中是沒有給出提示信息的,是由數據庫來決定的。
我們先簡單的看一個執行計劃的對比:
SQL> set autotrace traceonly
執行計劃一:
SQL> select count(*) from t;
COUNT(*)
----------
24815
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'T'
執行計劃二:
SQL> select count(*) from t;
COUNT(*)
----------
24815
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=26 Card=1)
1 0 SORT (AGGREGATE)
2 1 INDEX (FULL SCAN) OF 'T_INDEX' (NON-UNIQUE) (Cost=26 Card=28180)
這兩個執行計劃中,第一個表示求和是通過進行全表掃描來做的,把整個表中數據讀入內存來逐條累加;第二個表示根據表中索引,把整個索引讀進內存來逐條累加,而不用去讀表中的數據。但是這兩種方式到底哪種快呢?通常來說可能二比一快,但也不是絕對的。這是一個很簡單的例子演示執行計劃的差異。對於復雜的SQL(表連接、嵌套子查詢等),執行計劃可能幾十種甚至上百種,但是到底那種最好呢?我們事前並不知道,數據庫本身也不知道,但是數據庫會根據一定的規則或者統計信息(statistics)去選擇一個執行計劃,通常來說選擇的是比較優的,但也有選擇失誤的時候,這就是這次討論的價值所在。
ORACLE優化器模式
ORACLE優化器有兩大類,基於規則的和基於代價的,在SQLPLUS中我們可以查看init文件中定義的缺省的優化器模式。
SQL> show parameters optimizer_mode
NAME TYPE VALUE
------------------------------- ------ --------
optimizer_mode string CHOOSE
SQL>
這是ORACLE8.1.7 企業版,我們可以看出,默認安裝後數據庫優化器模式為CHOOSE,我們還可以設置為 RULE、FIRST_ROWS,ALL_ROWS。可以在init文件中對整個instance的所有會話設置,也可以單獨對某個會話設置:
SQL> ALTER SESSION SET optimizer_mode = RULE;
會話已更改。
SQL> ALTER SESSION SET optimizer_mode = FIRST_ROWS;
會話已更改。
SQL> ALTER SESSION SET optimizer_mode = ALL_ROWS;
會話已更改。