1. 程式人生 > >Oracle執行計劃名詞解釋

Oracle執行計劃名詞解釋

轉自:https://blog.csdn.net/luojinbai/article/details/42296271

1. 基於成本的優化器(cost-based plan); 

        它是看語句的代價(cost),這裡的代價主要指Cpu和記憶體;優化器在判斷是否使用這種方式的時候,主要參照的是表及索引的統計資訊;
    統計資訊給出表的大小、多少行、每行的長度等資訊。這些統計資訊起初在庫內是沒有的,是做analyze後才出現的,很多的時侯過期統計
    資訊會令優化器做出一個錯誤的執行計劃,因些應及時更新這些資訊。

2. 基於規則的優化器(rule-based plan): 
    
        優化器在分析SQL語句時,所遵循的是Oracle內部預定的一些規則。比如我們常見的,當一個where子句中的一列有索引時去走索引。

    查考:http://www.poluoluo.com/jzxy/200812/54048.html


3.  explain (analyze,verbose,costs,buffers,timing) select * from xxxx;

    explain引數解釋: 

    > ANALYZE :執行命令並顯示執行事件,預設false 
    > VERBOSE :對執行計劃提供額外的資訊,如查詢欄位資訊等,預設false 
    > COSTS :顯示執行計劃的,預設true 
    > BUFFERS :預設false,前置條件是analyze 
    > FORMAT :預設格式是text 

    PostgreSQL的cost常量如下 : 

    > seq_page_cost  -- 連續塊掃描操作的單個塊的cost. 例如全表掃描
    > random_page_cost  -- 隨機塊掃描操作的單個塊的cost. 例如索引掃描
    > cpu_tuple_cost  -- 處理每條記錄的CPU開銷(tuple:關係中的一行記錄)
    > cpu_index_tuple_cost  -- 掃描每個索引條目帶來的CPU開銷
    > cpu_operator_cost  -- 操作符或函式帶來的CPU開銷.(需要注意函式以及操作符對應的函式的三態, 執行計劃會根據三態做優化, 關係到多條記錄時三態對應的呼叫次數是需要關心的)


4. 執行計劃中的一些術語和關鍵字。

    執行計劃運算型別     操作說明                         是否有啟動時間
    -------------------------------------------------------------------
    Seq Scan             掃描表                             無啟動時間
    Index Scan           索引掃描                         無啟動時間
    Bitmap Index Scan     索引掃描                         有啟動時間
    Bitmap Heap Scan    索引掃描                         有啟動時間
    Subquery Scan       子查詢                             無啟動時間
    Tid Scan             ctid = …條件                     無啟動時間
    Function Scan         函式掃描                         無啟動時間
    Nested Loop         迴圈結合                         無啟動時間
    Merge Join             合併結合                         有啟動時間
    Hash Join             雜湊結合                         有啟動時間
    Sort                 排序,ORDER BY操作                有啟動時間
    Hash                 雜湊運算                         有啟動時間
    Result                 函式掃描,和具體的表無關         無啟動時間
    Unique                DISTINCT,UNION操作             有啟動時間
    Limit                LIMIT,OFFSET操作                 有啟動時間
    Aggregate             count, sum,avg, stddev聚集函式     有啟動時間
    Group                GROUP BY分組操作                 有啟動時間
    Append                UNION操作                         無啟動時間
    Materialize         子查詢                             有啟動時間
    SetOp                 INTERCECT,EXCEPT                有啟動時

   參考地址:http://my.oschina.net/congqian/blog/135872

 

============================================================================================

轉自:https://www.2cto.com/database/201608/543478.html

--名詞
-------------------------------
1)Rowid:系統自動生成的偽列,廣泛(每個表都有),只讀,伴隨行的整個生命週期。指出了該行所在的資料檔案、資料塊以及行在該塊中的位置。
Recursive SQL(遞迴SQL):
  觸發Recursive Call的情況: 
       (1)動態的分配空間:insert沒有足夠的空間來儲存row記錄時發生。
       (2)修改資料字典資訊:執行DDL語句時,ORACLE總是隱含的發出一些recursive SQL語句時發生。
       (3)沒有足夠空間儲存系統資料字典資訊:Shared Pool過小,data dictionary cache 也相應的過小,將資料字典資訊從硬碟讀入記憶體中時發生。
            在這種情況下,可以將recursive calls理解為從磁碟讀取資料字典的次數。
       (4)儲存過程、觸發器內有SQL呼叫時,也會產生recursive SQL。 
2)Row Source(行源):查詢中,上一操作返回的符合條件的行的集合(可以使全表,部分表和表連線之後的結果集)。
3)Predicate(謂詞):查詢中的WHERE限制條件
4)Driving Table(驅動表)/驅動行源(driving row source):該表又稱為外層表(OUTER TABLE)。
    一般說來,是應用查詢的限制條件後,小row source表作為驅動表,行源數量較多會影響後續操作效率。
    執行計劃中,應該為靠上的那個row source,一般將該表稱為連線操作的row source 1。
5)Probed Table(被探查表):該表又稱為內層表(INNER TABLE)。
    從驅動表中得到具體一行的資料後,在該表中尋找符合連線條件的行。為大row source且建立相應索引的表是效率高。
    一般將該表稱為連線操作的row source 2.
6)concatenated index(組合索引):由多個列構成的索引,如create index idx_emp on emp(col1, col2, col3, ……)
    在組合索引中有一個重要的概念:引導列(leading column),在上面的例子中,col1列為引導列。當我們進行查詢時可以使用“where col1 = ? ”,
    也可以使用“where col1 = ? and col2 = ?”,這樣的限制條件都會使用索引,但是“where col2 = ? ”查詢就不會使用該索引。
    所以限制條件中包含先導列時,該限制條件才會使用該組合索引。
7)selectivity(可選擇性):比較一下列中唯一鍵的數量和表中的行數,就可以判斷該列的可選擇性。
   如果該列的“唯一鍵的數量/表中的行數”的比值越接近1,則該列的可選擇性越高,該列就越適合建立索引,同樣索引的可選擇性也越高。
   在可選擇性高的列上進行查詢時,返回的資料就較少,比較適合使用索引查詢。
 
--oracle訪問資料的存取方法
--------------------------------
1) 全表掃描(Full Table Scans, FTS):讀取表中所有的行,並檢查每一行是否滿足語句的WHERE限制條件。
優化:增加每次讀取塊數,減少I/O次數(db_file_multiblock_read_count引數設定)--不是經常大表走FTS不作調整,調整可能影響cbo不走索引
使用條件:在較大的表上不建議使用全表掃描,除非取出資料的比較多,超過總量的5%-10%,或使用並行查詢功能。
select * from dual;
---------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     2 |     2   (0)|
|   1 |  TABLE ACCESS FULL| DUAL |     1 |     2 |     2   (0)|
---------------------------------------------------------------
 
2)通過ROWID的表存取(Table Access by ROWID或rowid lookup):直接訪問一個數據塊,Oracle存取單行資料的最快方法。
select * from tt where rowid='AAHSaUAALAAOaSAAAA';
------------------------------------------------------------------------
| Id  | Operation                  | Name | Rows  | Bytes | Cost (%CPU)|
------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |      |     1 |     5 |     1   (0)|
|   1 |  TABLE ACCESS BY USER ROWID| TT   |     1 |     5 |     1   (0)|
------------------------------------------------------------------------
 
3)索引掃描(Index Scan或index lookup):index獲取->rowid值(對於非唯一索引可能返回多個rowid值)->表資料
索引內容:索引值+此值行對應的ROWID值
常識:index常用,記憶體中,邏輯I/O,訪問快;
      大表,放在磁碟中,物理I/O,訪問慢;
      索引中的資料已經預排序。
案例分析:
    大表,取出資料的較多,超過總量的5%-10%->index獲取rowid->物理I/O訪問,慢;
    查詢的資料能全部在索引中找到,資料量無論多少,無論需不需要排序,都很快(不需要訪問表資料,直接從索引取值)
分類:
(1) 索引唯一掃描(index unique scan)
  通過唯一索引查詢一個數值經常返回單個ROWID.如果存在UNIQUE 或PRIMARY KEY 約束(它保證了語句只存取單行)的話,Oracle經常實現唯一性掃描。
select * from bd_corp where unitcode='J001';
--create unique index I_BD_CORP_1 on BD_CORP (UNITCODE);
 --------------------------------------------------------------------------------
| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |     1 |   293 |     1   (0)|
|   1 |  TABLE ACCESS BY INDEX ROWID| BD_CORP     |     1 |   293 |     1   (0)|
|   2 |   INDEX UNIQUE SCAN         | I_BD_CORP_1 |     1 |       |     1   (0)|
--------------------------------------------------------------------------------
(2) 索引範圍掃描(index range scan)
  使用一個索引存取多行資料,使用index rang scan的3種情況:
    (a) 在唯一索引列上使用了range操作符(> < <> >= <= between)
    (b) 在組合索引上,只使用部分列進行查詢,導致查詢出多行
    (c) 對非唯一索引列上進行的任何查詢(在非唯一索引上,謂詞可能返回多行資料,所以在非唯一索引上都使用索引範圍掃描)。
select * from bd_corp where begindate>'2016-01-01';
---------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              |    22 |  6446 |     9   (0)|
|   1 |  TABLE ACCESS BY INDEX ROWID| BD_CORP      |    22 |  6446 |     9   (0)|
|   2 |   INDEX RANGE SCAN          | I_BD_CORP_CT |    22 |       |     1   (0)|
---------------------------------------------------------------------------------
(3)索引全掃描(index full scan)
  與全表掃描對應,也有相應的全索引掃描。而且此時查詢出的資料必須全部從索引中可以直接得到。
  全索引掃描的例子:
select unitcode from bd_corp order by unitcode;
---------------------------------------------------------------------
| Id  | Operation        | Name        | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------
|   0 | SELECT STATEMENT |             |   791 |  3955 |     1   (0)|
|   1 |  INDEX FULL SCAN | I_BD_CORP_1 |   791 |  3955 |     1   (0)|
---------------------------------------------------------------------
(4)索引快速掃描(index fast full scan)
  掃描索引中的所有的資料塊,與index full scan很類似,區別是它不對查詢出的資料進行排序。可以使用多塊讀功能增加吞吐量,也可以並行讀入。
  select unitname,unitcode from bd_corp order by unitname;
---------------------------------------------------------------------------------
| Id  | Operation               | Name             | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |                  |   791 | 22939 |     6  (17)|
|   1 |  SORT ORDER BY          |                  |   791 | 22939 |     6  (17)|
|   2 |   VIEW                  | index$_join$_001 |   791 | 22939 |     5   (0)|
|   3 |    HASH JOIN            |                  |       |       |            |
|   4 |     INDEX FAST FULL SCAN| I_BD_CORP_1      |   791 | 22939 |     2   (0)|
|   5 |     INDEX FAST FULL SCAN| I_BD_CORP_2      |   791 | 22939 |     3   (0)|
---------------------------------------------------------------------------------
 
--表之間的連線/關聯(JOIN)
-------------------------------
*可並行訪問join的兩個row source的資料,但資料讀入記憶體形成row source後join的其它步驟一般是序列的。
1)按連線操作符分類(原理基本一樣):
  等值連線(如WHERE A.COL3 = B.COL4)、非等值連線(WHERE A.COL3 > B.COL4)、外連線(WHERE A.COL3 = B.COL4(+))。
 
2)連線型別:
(1)排序-合併連線(Sort Merge Join, SMJ):先排序,後連線
    內部連線過程:<1>生成row source1,按照連線操作關聯列排序
                 <2>生成row source2,按照連線操作關聯列排序
                 <3>按條件連線兩個行源
                 *<1>,<2>可並行,<3>序列
  優勢:若2個row source都已經預先排序,則效率較高。(預先排序包含:已被索引的列/row source在前面的步驟中已經排序)
         對於非等值連線,這種連線方式的效率是比較高的。
         對於將2個較大的row source做連線,該連線方法比NL連線要好一些。
    劣勢:sort費時、費資源,特別對於大row source。
(2)巢狀迴圈(Nested Loops, NL):驅動表的每一行逐一到被探查表去匹配(2層巢狀迴圈)。
  內部連線過程(有驅動表(外部表)的概念):
      Row source1的Row 1 —— Probe ->Row source 2
      Row source1的Row 2 —— Probe ->Row source 2
      Row source1的Row 3 —— Probe ->Row source 2
      ……
      Row source1的Row n —— Probe ->Row source 2
    優勢:逐一匹配,先返回已經連線的行,響應快
          驅動表較小,且被探查表上有唯一索引或高選擇性非唯一索引時,則效率較高。
          並行查詢(硬體支援):常選擇大表作為驅動表,因為大表可以充分利用並行功能。
    劣勢:內外表顛倒效率差。
(3)雜湊連線(Hash Join)
    引數: HASH_JOIN_ENABLED=TRUE,預設情況下該引數為TRUE
           hash_area_size --因為雜湊連線會在該引數指定大小的記憶體中執行,過小的引數會減小效能。
               alter session set workarea_size_policy=MANUAL;--先設定workarea_size_policy才能生效
               alter session set hash_arear_size=200m;
  優勢:設定好引數,效率優於SMJ和NL(2個較大的row source之間連線時會取得相對較好的效率,在一個row source較小時則能取得更好的效率。)
    劣勢:只能用於等值連線中  只能用在CBO優化器中  需要設定合適的引數才能取得較好的效能。
(4)笛卡兒乘積(Cartesian Product):無關聯關係的row source連線
  通常由編寫程式碼疏漏造成(即程式設計師忘了寫關聯條件)。笛卡爾乘積是一個表的每一行依次與另一個表中的所有行匹配。
select a.ta,b.ta from tt a ,tt1 b ;
------------------------------------------------------------------
| Id  | Operation            | Name | Rows  | Bytes | Cost (%CPU)|
------------------------------------------------------------------
|   0 | SELECT STATEMENT     |      |    16 |    64 |    34   (0)|
|   1 |  MERGE JOIN CARTESIAN|      |    16 |    64 |    34   (0)|
|   2 |   TABLE ACCESS FULL  | TT1  |     4 |     8 |     8   (0)|
|   3 |   BUFFER SORT        |      |     4 |     8 |    26   (0)|
|   4 |    TABLE ACCESS FULL | TT   |     4 |     8 |     7   (0)|
------------------------------------------------------------------
--CARTESIAN關鍵字指出了在2個表之間做笛卡爾乘積
在特殊情況下我們可以使用笛卡兒乘積,如在星形連線中,除此之外,我們要儘量不使用笛卡兒乘積。
 
 
--autotrace statistics 名詞解釋
-------------------------------
recursive calls:遞迴呼叫
db block gets:通過update/delete/select for update讀的次數。在當前讀模式下所讀的塊數,比較少和特殊,例如資料字典資料獲取。
              在DML中,更改或刪除資料是要用到當前讀模式。
consistent gets:在一致讀模式下所讀的快數,包括從回滾段讀的快數。 即通過不帶for update的select 讀的次數。
physical reads:物理讀(從磁碟上讀取資料塊的數量)。
               其產生的主要原因是:1.在資料庫快取記憶體中不存在這些塊; 2.全表掃描;  3.磁碟排序。 
redo size:DML生成的redo的大小。
sorts (memory):在記憶體執行的排序量。 
sorts (disk):在磁碟執行的排序量。
2091 bytes sent via SQL*Net to client     從SQL*Net向客戶端傳送了2091位元組的資料 
416 bytes received via SQL*Net from client  客戶端向SQL*Net傳送了416位元組的資料。
 
LOGIC IO(邏輯讀次數)= db block gets + consistent gets
 
example:
 1188  recursive calls--遞迴呼叫
      0  db block gets
    282  consistent gets
     10  physical reads
      0  redo size
 3222  bytes sent via SQL*Net to client
    514  bytes received via SQL*Net from client
      4  SQL*Net roundtrips to/from client
     23  sorts (memory)
      0  sorts (disk)
     33  rows processed