optimizer_mode優化器模式


查詢優化器最主要的工作就是接受輸入的SQL以及各種環境參數、配置參數,生成合適的SQL執行計划(Execution Plan)。

Query Optimizer一共經歷了兩個歷史階段:

  • RBO: Rule-Based Optimization 基於規則的優化器
  • CBO: Cost-Based Optimization 基於代價的優化器

關於RBO與CBO,一個形象的比喻:大數據時代到來以前,做生意或許憑借多年累計 下來的經驗規則(RBO)就能夠很好的做出決策,跟隨市場變化。但是大數據時代,如果做生意還是靠以前憑經驗做決策,而不是靠大數據、數據分析、數據挖掘做決策,那么就有可能做出錯誤的決策。這也就是越來越多的公司對BI、數據挖掘越來越重視的緣故

一、RBO優化器

RBO(Rule Based Optimizer,基於規則的優化器)就是在優化器里面嵌入15種規則,它根據ORACLE指定的優先順序規則,對指定的表進行執行計划的選擇。執行SQL語句符合哪種規則,就按照規則定制出相應的SQL執行計划。比如在規則中,索引的優先級大於全表掃描;RBO是根據可用的訪問路徑以及訪問路徑等級來選擇執行計划,在RBO中,SQL的寫法往往會影響執行計划,它要求開發人 員非常了解RBO的各項細則,菜鳥寫出來的SQL腳本性能可能非常差。由於它他是一種過時呆板的優化器,Oracle官方已不再支持RBO服務。

   15種規則及ranking:

二、CBO優化器

CBO是一種比RBO更加合理、可靠的優化器,它是從ORACLE 8中開始引入,但到ORACLE 9i 中才逐漸成熟。進入Oracle 10g之后,Query Optimizer就已經將CBO(Cost Based Optimizer,基於代價的優化器)作為默認優化器,並且Oracle官方不再支持RBO服務。

它的思路是讓Oracle獲取所有的執行計划的相關信息,利用系統統計量進行各種執行路徑試算,計算各種可能“執行計划”的“代價”,即COST,獲取相對相對成本最低的執行計划,作為實際運行方案。它依賴數據庫對象的統計信息,統計信息的准確與否會影響CBO做出最優的選擇。如果對一次執行SQL時發現涉及對象(表、索引 等)沒有被分析、統計過,那么ORACLE會采用一種叫做動態采樣的技術,

動態統計量收集是Oracle CBO優化器的一種特性。優化器生成執行計划是依據成本cost公式計算出的,如果相關數據表沒有收集過統計量,又要使用CBO的機制,就會引起動態采樣(Dynamic Sampling),。

動態采樣(dynamic sampling)就是在生成執行計划是,以一個很小的采用率現進行統計量收集, 動態的收集表和索引上的一些數據信息。由於采樣率低,采樣過程快但是不精確,而且采樣結果不會進入到數據字典中。

CBO查詢優化器由查詢轉換器(Query Transform)、代價估算器(Estimator)和計划生成器(Plan Generator)組成。

clip_image001

CBO優化器有兩種可選的運行模式:

2.1 FIRST_ROWS(n)

當設置優化器模式為:FIRST_ROWS(n)時,意味着Oracle在執行SQL語句時,優先考慮將結果集中的前n條記錄以最快的速度反饋回 來,而其他結果並不需要同時反饋,也就是說在處理數據的時候,后面的數據可能還沒提取出來,前面的數據已經返回給用戶了,這種需求在網站搜索或者BBS的 分頁上經常看到。比如每次只顯示查詢信息的前20條,這時設置FIRST_ROWS(20)就非常合適。對於分頁操作,越靠前的頁,顯示結果需要的時間將越短。

需要注意的是排序使用的X必須創建有索引,否則CBO會忽略FIRST_ROWS(n)而使用ALL_ROWS.

2.2 ALL_ROWS

CBO的模式為ALL_ROWS時,意味着我們需要Oracle以最快的速度將SQL執行完畢,將結果集全部返回。它和FIRST_ROWS(n) 的區別在於,ALL_ROWS強調整體的執行效率,而FIRST_ROWS(n)強調以最快的速度返回前n條記錄。ALL_ROWS在OLAP系統中使用 的比較多,它的目的在於快速獲取執行結果的最后一條記錄。

三、CHOOSE——兩個時代的過渡

在Oracle 9i一個時期,optimizer_mode的默認參數取值為CHOOSE。那個時期是query optimizer從RBO向CBO轉換的時代,Oracle選擇了漸變式的轉換。由於那時沒有專門的夜間統計量收集作業,很多時候數據表是沒有統計量的。加之動態抽樣技術的不成熟,所以CBO的應用存在一些障礙。在這個時期,Oracle提出了CHOOSE作為優化器默認模式。

CHOOSE是介於自動選擇切換RBO和CBO。如果SQL涉及的數據表中有一個有統計量,那么該SQL就是用CBO優化器。否則就是用RBO。動態采樣技術是在CBO優化器前提下的技術方案。

SCOTT@PDBORCL>  alter session set optimizer_mode=choose;

會話已更改。

SCOTT@PDBORCL> set autotrace traceonly;
SCOTT@PDBORCL>  exec dbms_stats.delete_table_stats('scott','emp',cascade_columns => true,cascade_indexes => true);

PL/SQL 過程已成功完成。

SCOTT@PDBORCL> select ename from emp ;

已選擇 14 行。


執行計划
----------------------------------------------------------
Plan hash value: 3956160932

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|   1 |  TABLE ACCESS FULL| EMP  |
----------------------------------

Note
-----
   - rule based optimizer used (consider using cbo)


統計信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
        732  bytes sent via SQL*Net to client
        544  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         14  rows processed

SCOTT@PDBORCL> exec dbms_stats.gather_table_stats (ownname => 'scott',tabname => 'emp');

PL/SQL 過程已成功完成。

SCOTT@PDBORCL> select ename  from emp;

已選擇 14 行。


執行計划
----------------------------------------------------------
Plan hash value: 3956160932

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    14 |    84 |     3   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| EMP  |    14 |    84 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------


統計信息
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          8  consistent gets
          0  physical reads
          0  redo size
        732  bytes sent via SQL*Net to client
        544  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         14  rows processed

SCOTT@PDBORCL>
View Code

 

四、optimizer_mode的查看與修改

通過優化器參數optimizer_mode,我們可以控制Oracle優化器生成不同模式下的執行計划。

4.1查看optimizer_mode

parameter optimizer_mode

SCOTT@PDBORCL> show parameter optimizer_mode

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_mode                       string      ALL_ROWS

SCOTT@PDBORCL> select name, value from v$parameter where name='optimizer_mode';

NAME                                                                             VALUE
-------------------------------------------------------------------------------- ---------------------------------------
optimizer_mode                                                                   ALL_ROWS

SCOTT@PDBORCL>

4.2修改optimizer_mode

ORACLE 10g 優化器可以從系統級別、會話級別、語句級別三種方式修改優化器模式,非常方便靈活。 其中optimizer_mode可以選擇的值有: first_rows_n,all_rows.  其中first_rows_n又有first_rows_1000, first_rows_100, first_rows_10, first_rows_1

系統級別

可以通過下面語句修改optimizer_mode

alter system set optimizer_mode=all_rows scope=both;

會話級別

會話級別修改優化器模式,只對當前會話有效,其它會話依然使用系統優化器模式。

 alter session set optimizer_mode=first_rows_100;

語句級別

語句級別通過使用提示hints來實現。

select /*+ rule */ * from emp;

參考:

ORACLE優化器RBO與CBO介紹總結

淺談optimizer_mode優化器模式


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM