ORACLE優化器

一 ORACLE優化器概述
ORACLE優化器是用於生成SQL語句訪問數據庫時使用的執行計劃的。ORACLE優化器通過使用ORACLE蒐集的關於數據庫對象的統計數據來生成SQL語句的訪問計劃(使用什麼對象)並執行計劃(使用何種操作)。


二 ORACLE優化器的分類
ORACLE優化器分爲三類:
1) RULE優化器:基於規則的優化器相對比較簡單,通過檢查數據庫的可用路徑並將這些路徑與路徑表進行比較,從而確定SQL語句的執行計劃。RULE優化的過程中不需要任何表或索引的統計信息,而且也會忽略任何表或索引的統計信息
2) COST優化器:基於開銷的優化器相對比較複雜,通過使用數據庫的結構和數據等信息來選擇最優的執行計劃。優化的過程中需要相關表和索引的統計信息。
3) CHOOSE優化器:在存在相關統計信息的情況下采用基於開銷的優化器,在不存在相關統計信息的情況下才用基於規則的優化器。這是8I中默認的優化器工作方式


三 查詢當前優化器的工作方式
查詢當前優化器的工作方式比較簡單的方法有以下兩種:
1) 查看ORACLE數據庫的初始化文件,看看初始化參數optimizer_mode的取值
2) SQL> select name,value from v$parameter where name = 'optimizer_mode';
NAME         VALUE
---------------     ---------------------------------------------------------
optimizer_mode  CHOOSE


四 修改優化器的工作模式
可以使用下面的兩種方法來選擇優化器模式(基於開銷的模式和基於規則的模式):
1) 初始化參數optimizer_mode
2) alter session 命令的 optimizer_goal參數
選擇優化器模式時所能使用的選項
choose:這個選項允許優化器根據特定表或索引的統計數據的可用性選擇優化模式。如果sql語句中涉及到的表中有一個表有統計數據,那麼優化器將選擇基於開銷的優化方法;否則如果所有表都沒有統計數據,那麼優化器將選擇基於規則的優化模式
rule:這個選項將導致優化器總是使用基於規則的優化方法,而不管系統中是否存在被訪問表的統計數據
all_rows:這個選項將導致優化器對所有的sql語句都使用基於開銷的優化方法,即使對於系統中不存在可用統計數據的表,情況也是如此。這個選項的目的是使用最少的系統資源獲得最大的吞吐量,力求完成sql語句的總花費爲最少
first_rows_n:這個選項將導致優化器對所有的sql語句都使用基於開銷的優化方法,即使對於系統中不存在可用統計數據的表,情況也是如此。這個選項的目的是獲得最快的響應時間,力求最快返回結果中的前n條記錄


五 基於規則的優化器
因爲我們現在的測試環境和所有的醫保中心以及定點醫療機構都是採用默認的choose優化器選項,而且所有的表和索引等也沒有相關的統計信息,所以實際上oracle數據庫都是運行在rule的優化器模式下。下面詳細的介紹一下基於規則的優化器模式,對基於開銷的優化器僅做簡單的介紹。
在基於規則的和基於開銷的優化器中,基於規則的優化器相對來說比較簡單。在基於規則的優化方法中,優化器通過檢查數據庫的可用路徑並將這些路徑與路徑表進行比較,從而確定sql語句的執行計劃。下面的表中包含了與各種不同訪問路徑相關的開銷
級別 訪問路徑
1 通過rowid訪問單行數據
2 通過簇連接訪問單行數據
3 通過帶惟一鍵或主鍵的散列簇訪問單行數據
4 通過惟一鍵或主鍵訪問單行數據
5 簇連接
6 散列簇鍵
7 索引簇鍵
8 複合鍵
9 單字段索引
10 在索引字段上有邊界的範圍內搜索數據
11 在索引字段上無邊界的範圍內搜索數據
12 排序合併連接
13 搜索索引字段的最大或最小值
14 對索引字段使用order by操作
15 全表掃描
舉個最簡單的例子來說明基於規則的優化器如果選擇執行路徑
建立測試用表
SQL> drop table test;
表已丟棄。
SQL> create table test
  2  (id varchar2(3),
  3  name varchar2(10))
  4  tablespace test;
表已創建。
SQL> insert into test values ('001','tom');
已創建 1 行。
SQL> commit;
提交完成。

沒有建立的索引的情況下,該sql執行的唯一方式就是全表掃描(即使全表掃描被規則優化器認爲是最慢的一種方式)
SQL> set autotrace on
SQL> select * from test where id='001';
ID  NAME
--- ----------
001 tom
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   TABLE ACCESS (FULL) OF 'TEST'

在test的id字段上建立索引後,上面這條sql語句就存在兩種執行方案,一是全表掃描(15),另一種就是單字段索引(9)。Oracle根據前面的規則認爲後者的開銷比較小,所以優化器選擇通過索引的掃描。
SQL> create index idx_test on test(id);
索引已創建。
SQL> select * from test where id='001';
ID  NAME
--- ----------
001 tom
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=CHOOSE
   1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST'
   2    1     INDEX (RANGE SCAN) OF 'IDX_TEST' (NON-UNIQUE)

上面的這個例子說明了基於規則的優化器的工作方式。基於規則的優化器原理比較簡單,可以給系統提供比較好的執行計劃的穩定性。

六 基於開銷的優化器
基於開銷的優化器需要表或索引上的統計信息,他根據這些統計信息來爲sql選擇一條他認爲是開銷最小的執行路徑。由於數據庫裏面的數據是一直在變化的,所以統計信息也應該及時的更新,這樣纔可以爲基於開銷提供準確的信息,爲sql提供更加優化的方案。
SQL> alter session set OPTIMIZER_MODE=all_rows;
會話已更改。
SQL> analyze table test compute statistics;
表已分析。
SQL> select * from test where id='001';
ID  NAME
--- ----------
001 tom
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=1 Card=1 Bytes=6)
   1    0   TABLE ACCESS (FULL) OF 'TEST' (Cost=1 Card=1 Bytes=6)

雖然test表上存在索引,但是由於表中僅有一條記錄,所以全表掃描的開銷應該比通過索引來查找記錄要小的多。因此基於開銷的優化器選擇了全表掃描。從上面的兩個例子的對比來看只要有了統計信息,基於開銷的優化器比基於規則的優化器要聰明的多。

七 總結
一般來說8i以下的數據庫使用基於規則的優化器比較合適,因爲這些版本里面的基於開銷的優化器並不完善,爲sql語句提供的執行路徑並不總是最優的;而8i以及以上的版本,基於開銷的優化器已經比較完善了,可以很好的代替基於規則的優化器來工作了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章