2013-03-22 88 views
4

我想了解在Oracle的解釋計劃,想知道而形成的解釋計劃瞭解在Oracle的解釋計劃

我是測試在HR模式目前在Oracle 11g中

一個簡單的查詢哪些條件甲骨文認爲
select * from countries 
where region_id in (select region_id from regions where region_name = 'Europe'); 

當我運行以下查詢:

explain plan for 
select * from countries 
where region_id in (select region_id from regions where region_name = 'Europe'); 

SELECT * FROM table(dbms_xplan.display(null,null,'basic')); 

我在解釋表下面的輸出:

-------------------------------------------------------- 
| Id | Operation     | Name   | 
-------------------------------------------------------- 
| 0 | SELECT STATEMENT    |     | 
| 1 | NESTED LOOPS    |     | 
| 2 | INDEX FULL SCAN   | COUNTRY_C_ID_PK | 
| 3 | TABLE ACCESS BY INDEX ROWID| REGIONS   | 
| 4 | INDEX UNIQUE SCAN   | REG_ID_PK  | 
-------------------------------------------------------- 

在這裏,我觀察到,外部查詢被首先執行,即國家表首先執行如用行3.

現在我增加了一個索引上的區域表的REGION_NAME跑解釋計劃再次 ,得到了下面的輸出現在

-------------------------------------------------------------- 
| Id | Operation     | Name     | 
-------------------------------------------------------------- 
| 0 | SELECT STATEMENT    |      | 
| 1 | NESTED LOOPS    |      | 
| 2 | TABLE ACCESS BY INDEX ROWID| REGIONS    | 
| 3 | INDEX RANGE SCAN   | REGIONNAME_REGIONS_IX | 
| 4 | INDEX UNIQUE SCAN   | COUNTRY_C_ID_PK  | 
| 5 | INDEX RANGE SCAN   | COUNTRIES_REGIONID_IX | 
-------------------------------------------------------------- 

我的問題是:

  1. 應該不是內部查詢首先執行,不管索引是否存在
  2. 如果添加索引改變執行計劃,還有哪些其他功能可以改變它?
  3. 在一般情況下,執行過程是什麼樣的,它是順序的(首先執行首先發生的連接,然後進入查詢中的下一個連接)?

在此先感謝您的幫助。

-Varun

回答

2

解釋計劃嚴重依賴基於成本的優化器(CBO)。您可以通過收集您正在查詢的表格上的統計數據來幫助完成此過程。關於爲什麼指數會改變計劃,這是因爲您已經向CBO提供了以前沒有的重要信息。這相當於我問你這個問題:

沒有索引:
「街道在哪裏?」 「

有了索引:
」哪裏有一個藍色的房子呢?

第二個問題提供了更大的上下文,因此您可以更快地推斷出結果,而且您​​不必枚舉所有這些街道上的東西。

您可以提供提示,查詢即:

select /*+ parallel */ * from table
給予提示並行運行此查詢。

對於第三個問題,我想是Oracle流程的一部分,並且沒有記錄供世界使用。

在第一個問題中,不一定,它都是基於成本的。

1

我不知道他們是否改變了11g執行計劃輸出中的任何內容,但是您確定您向我們展示了正確的查詢嗎?您正在從表國家中選擇所有列(select *),但解釋計劃不顯示任何表訪問?還是COUNTRY_C_ID_PK包含所有列?

我希望下面的計劃(不包括指數):

SELECT 
    NESTED LOOP 
    FULL TABLE SCAN (regions) 
    TABLE ACCESS BY INDEX ROWID (countries) 
     INDEX RANGE SCAN (COUNTRIES_REGIONID_IX) 

有了索引,我希望這樣的事情:

SELECT 
    NESTED LOOP 
    TABLE ACCESS BY INDEX ROWID (regions) 
     INDEX RANGE SCAN (REGIONNAME_REGIONS_IX) 
    TABLE ACCESS BY INDEX ROWID (countries) 
     INDEX RANGE SCAN (COUNTRIES_REGIONID_IX) 

對於您的問題:

  1. Oracle可能會根據可用的統計信息從內部或外部查詢中驅動查詢
  2. 有很多東西影響執行計劃...
  3. Oracle一次只能連接兩個表(或行源)。加入的結果也是可以加入到下一個表格的行來源
1

基於成本的優化器會經歷幾個階段,包括查詢轉換。您的查詢幾乎肯定由優化重寫:

選擇國家* 從國家加入上(countries.region_id = regions.region_id) 其中regions.region_name =「歐洲」的區域。

因此,原始查詢中表示的內部和外部查詢的概念可能不適用於轉換後。順便說一下,這就是爲什麼涉及EXISTS()和IN()的爭論經常沒有實際意義 - 兩種情況下的查詢通常都可以重寫爲連接。

之間信息的優化器使用(取決於版本)是:

  1. 在桌子上
  2. 統計數據表中的列統計
  3. 表列的
  4. 直方圖值指標
  5. 存在
  6. 指數的大小和類型以及統計指數 - 特別是聚類因子
  7. 存在的約束 - 包括非空和檢查約束。
  8. 每秒單塊和多塊讀取和cpu操作的估計成本。
  9. 分區
  10. 物化視圖和/或查詢重寫聲明的存在和狀態。
  11. 以前版本的查詢的性能。

所以簡而言之,不要驚訝於優化器所做的任何事情。這是一個非常複雜的工具包。