Oracle 配置查詢優化器

2021-06-16 10:09:30 字數 3535 閱讀 8743

一. 背景介紹

查詢優化器對於sql語句的效能非常重要,因為我們寫的sql語句最後被資料庫執行,是通過查詢優化器生成執行計畫實現的。如果查詢優化器生成的執行計畫低效,那麼就會導致低劣的效能。有一些引數的配置能夠影響到查詢優化器生成高效的執行計畫,但也是有風險的。總之,可以這麼說,配置查詢優化器的代價是昂貴的,但值得為此付出。

二. 配置線路圖

我們可以按照如下圖所示的路線,來乙個個引數進行配置

下面是對圖中標有數字步驟的描述:(後面再詳細描述各個引數的含義)

1. 這兩個引數需要調整:optimizer_mode 和 db_file_mutiblock_read_count

2. 這一步的引數預設值已經很合適了,通常沒必要調整。這些引數主要是要啟用或者禁止查詢優化器某一些特性

3. 收集系統統計資訊和物件統計資訊,這一步是必須做到,不過oracle10g中已經自己做了。

4. 記憶體中儲存資料時選擇手動還是自動調整記憶體的使用量。

5. 自動調整的話,需要設定pga_aggregate_target引數。

6. 手動調整的話,需要設定這些引數。

7. 測試應用程式是否達到預期的效能

8. 如果查詢優化器能為大多數sql生成高效執行計畫,則配置成功,否則需要進行第9步。

9. 如果查詢優化器傾向於使用過多或者過少索引,通常需要調整引數optimizer_index_caching和optimizer_index_cost_adj

三. 引數說明

根據引數的功能分為兩組:查詢優化器引數-只對查詢優化器的操作起作用,pga引數-影響程式全域性區(pga)的記憶體布局。

查詢優化器引數

1. optimizer_mode

查詢優化器是為了找乙個最高效的執行計畫,這個引數用來定義什麼是「高效」,比如是更快還是占用資源更少。在oracle10g中只支援兩個引數值:

all_rows:提供全部資料

first_rows(n):n為大於0的自然數,表示盡快傳輸前面n條資料(比如分頁查詢的時候,我第一次只查詢前面10條資料)

oracle10g預設為all_rows,可以再資料庫級別,會話級別,或者執行sql的時候修改該引數的值。

資料庫級別:alter system set optimizer_mode=first_rows(10) scope=spfile;

會話級別:alter session set optimizer_mode=first_rows(10);

sql級別:select /*+ first_rows(10) */ id,name from t1 order by id;

其實,預設all_rows是最好的方式,如果確實是只要查詢小部分資料,可以在sql級別加上提示,看是否能提高效能。

2. db_file_multiblock_read_count

在多塊讀的情況下(比如全表掃瞄),該引數說明一次最多可讀取的資料塊數目。設定得太小的話,效率低。設定得太高也不見得就好(太高,會受i/o最大吞吐量限制。比如設定成一次最多讀取1024塊,但i/o最大吞吐量只允許32塊,那一次最多也只讀取32塊。而且一次讀取很多塊,開銷會偏高。)應該通過測試,才能知道應該把該引數設定成哪乙個值。

測試過程:

1. 建立一張大表,比如上千萬行級別的資料

2. 迴圈設定該引數的值,檢視全表掃瞄的速度。類似於以下語句:

declare

l_count pls_integer;

l_time pls_integer;

l_starting_time pls_integer;

l_ending_time pls_integer;

begin

dbms_output.put_line('dbfmbrc seconds');

for l_dbfmbrc in 1..32

loop

execute immediate 'alter session set db_file_multiblock_read_count='||l_dbfmbrc;

l_starting_time := dbms_utility.get_time();

select /*+ full(t) */ count(*) into l_count from big_table t;

l_ending_time := dbms_utility.get_time();

l_time := round((l_ending_time-l_starting_time)/100);

dbms_output.put_line(l_dbfmbrc||' '||l_time);

end loop;

end;

/

3. optimizer_index_cost_adj影響走索引掃瞄的開銷計算。 取值範圍1到10000.預設值為100,超過100後,走索引掃瞄的開銷越高,從而使得查詢優化器更加傾向於使用全表掃瞄。相反,小於100,索引掃瞄的開銷就越低,從而使得查詢優化器更加傾向於使用索引掃瞄。從下面索引掃瞄開銷計算公式可以看出:

io_cost=(blevel+(leaf_blocks+culstering_factor)*selectivity) *optimizer_index_cost_adj/100.

一般是預設值不需要修改,但是如果發現本應該走索引掃瞄結果走了全表掃瞄,可以適當調低該值,但是,這個值不應該設定過低,因為,過低的話,如果兩個索引掃瞄的開銷不同,可能通過該公式一算,開銷就變成一樣的了。總之,不建議修改該引數的值。

pga引數

1. workarea_size_policy

管理工作區域記憶體(pga)的方式,

auto:oracle10g預設方式,委託給記憶體管理器自動管理(建議不需要修改)

manual:oracle9i預設方式,oracle9i沒有自動管理功能。

2. pga_aggregate_target

如果是自動管理pga,那麼該引數用於指定例項可用的pga的大小,預設是sga的20%。即使今後用的記憶體超過了設定的值,也沒有關係,oracle會自動增大pga的值。比如該引數設定的是200m,今後某一時刻,需要300m,也是沒問題的,會自動增長。

3. sort_area_size

手動管理pga,該引數指定分配多大的記憶體用於排序操作,過小的話,會影響效能,過大的話浪費空間。很難說乙個合適的預設值,因為使用者場景變化非常大,實際情況得實際處理。

4. hash_area_size

手動管理pga,該引數用於指定雜湊連線的工作區域大小,同樣建議它的值也很困難。如果過小,那麼查詢優化器就會高估雜湊連線的開銷,偏向於合併連線。

配置查詢優化器

1.配置還是不配置 沒有任何乙個引數的選值適用於所有情況 2.配置路線圖 3.設定正確的引數 optimizer mode 查詢優化器依據該值決定哪個是最高效的執行計畫 all rows 獲取所的記錄更重要 first rows n n 1,10,100.1000 獲取前幾行更重要 optimize...

Oracle 查詢優化器 改寫查詢語句

start 當我們執行一條查詢語句的時候,我們只告訴 oracle 我們想要哪些資料,至於資料在 怎麼找,那是查詢優化器的事情,優化器需要改寫查詢語句,決定訪問路徑 如 全表掃瞄,快速全索引掃瞄,索引掃瞄 決定表聯接順序等。至於選擇哪種方式,優化器需要根據資料字典做出判斷。那優化器如何改寫查詢語句呢...

oracle查詢優化

1 in 操作符 用 in 寫出來的 sql的優點是比較容易寫及清晰易懂,這比較適合現代軟體開發的風格。但是用 in 的 sql 效能總是比較低的,從 oracle 執行的步驟來分析用 in 的 sql 與不用 in 的 sql有以下區別 oracle 試圖將其轉換成多個表的連線,如果轉換不成功則先...