3

假設我們有以下問題:爲什麼優化程序計劃與實驗性查詢運行不相關?

  • 給定一個表有一列'X',含有某些行隨機 整數從1到100:

    CREATE TABLE xtable(x) AS 
        SELECT ceil(dbms_random.value * 100) 
        FROM dual 
        CONNECT BY level <= 1000000; 
    
  • 我們必須刪除重複所以所有不同的整數都保留在表中。


讓我們考慮三種解決方案(平均執行時間和優化計劃)之下。

我必須補充,實驗表明:

  • 溶液1和2是可伸縮的,並具有與每個行量步驟(附表測試高達10萬行)
  • 溶液3具有線性時間的增長指數時間增長大約像3 * exp(0.6 * N)

我們看到,對於解決方案2優化計劃給無關的實驗結果的期望, 的甚至相反的對他們說:

  • 成本和其他值都幾乎是在計劃2相同,3
  • 執行時間實際上是解決辦法1相同,2

而且在這個實驗表 的收集統計信息的存在與否不會影響優化程序計劃和執行時間。


請解釋爲什麼我不能在案件2

是什麼原因導致的優化忽略線性和指數的複雜性之間的明顯差異信任優化計劃?


解決方案:
1.

DELETE xtable WHERE rowid IN (
     SELECT ri from (
     SELECT rowid            AS ri, 
       row_number() OVER(PARTITION BY x ORDER BY null) AS rn 
      FROM xtable 
    ) 
     WHERE rn > 1 
) 


Exe time: 14 - 16 secs 

Plan: 
------------------------------------------------------------------------------------ 
| Id | Operation    | Name  | Rows | Bytes | Cost | Time  | 
------------------------------------------------------------------------------------ 
| 0 | DELETE STATEMENT   |   | 1000000 | 15000000 | 5119 | 00:00:01 | 
| 1 | DELETE     | XTABLE |   |   |  |   | 
| * 2 | HASH JOIN SEMI  |   | 1000000 | 15000000 | 5119 | 00:00:01 | 
| 3 |  TABLE ACCESS FULL | XTABLE | 1000000 | 3000000 | 280 | 00:00:01 | 
| 4 |  VIEW     | VW_NSO_1 | 1000000 | 12000000 | 2976 | 00:00:01 | 
| * 5 |  VIEW    |   | 1000000 | 25000000 | 2976 | 00:00:01 | 
| 6 |  WINDOW SORT  |   | 1000000 | 3000000 | 2976 | 00:00:01 | 
| 7 |  TABLE ACCESS FULL | XTABLE | 1000000 | 3000000 | 280 | 00:00:01 | 
------------------------------------------------------------------------------------ 
Predicate Information (identified by operation id): 
------------------------------------------ 
* 2 - access(ROWID="RI") 
* 5 - filter("RN">1) 

2.

DELETE xtable WHERE (x, rowid) NOT IN (SELECT x, min(rowid) FROM xtable GROUP BY x) 

Exe time: 15 - 17 secs 

Plan: 
-------------------------------------------------------------------------------------- 
| Id | Operation     | Name | Rows | Bytes | Cost  | Time  | 
-------------------------------------------------------------------------------------- 
| 0 | DELETE STATEMENT   |  | 50000 | 150000 | 278162850 | 03:01:06 | 
| 1 | DELETE     | XTABLE |   |   |   |   | 
| 2 | FILTER     |  |   |   |   |   | 
| 3 |  TABLE ACCESS FULL  | XTABLE | 1000000 | 3000000 |  281 | 00:00:01 | 
| 4 |  FILTER    |  |   |   |   |   | 
| 5 |  SORT GROUP BY NOSORT |  | 1000000 | 3000000 |  280 | 00:00:01 | 
| 6 |  TABLE ACCESS FULL | XTABLE | 1000000 | 3000000 |  280 | 00:00:01 | 
-------------------------------------------------------------------------------------- 
Predicate Information (identified by operation id): 
------------------------------------------ 
* 5 - access(INTERNAL_FUNCTION("X")=INTERNAL_FUNCTION("X") AND INTERNAL_FUNCTION(ROWID)=INTERNAL_FUNCTION("MIN(ROWID)")) 
* 5 - filter(INTERNAL_FUNCTION(ROWID)=INTERNAL_FUNCTION("MIN(ROWID)") AND INTERNAL_FUNCTION("X")=INTERNAL_FUNCTION("X")) 

3。

DELETE xtable a WHERE EXISTS(select 1 FROM xtable b WHERE a.x = b.x AND a.rowid < b.rowid) 

Exe time: 970 - 990 sec 

Plan: 
---------------------------------------------------------------------------------------------- 
| Id | Operation      | Name | Rows | Bytes | Cost  | Time  | 
---------------------------------------------------------------------------------------------- 
| 0 | DELETE STATEMENT     |  | 50000 | 300000 | 278208956 | 03:01:08 | 
| 1 | DELETE       | XTABLE |   |   |   |   | 
| * 2 | FILTER      |  |   |   |   |   | 
| 3 |  NESTED LOOPS SEMI   |  | 50000 | 300000 | 278208956 | 03:01:08 | 
| 4 |  TABLE ACCESS FULL   | XTABLE | 1000000 | 3000000 |  280 | 00:00:01 | 
| * 5 |  TABLE ACCESS BY ROWID RANGE | XTABLE | 50000 | 150000 |  278 | 00:00:01 | 
----------------------------------------------------------------------------------------------  
Predicate Information (identified by operation id): 
------------------------------------------ 
* 2 - filter(:VAR2=:VAR1) 
* 5 - access("B".ROWID>"A".ROWID) 

計劃被上Oracle 12.1.0.2.0

+0

當你說「不能信任案例2中的優化器計劃」時,你是什麼意思?你認爲2和3的執行計劃是相似的嗎?執行計劃3有兩個嵌套循環半連接的全表掃描,然後進行過濾。執行計劃2排序後跟一個過濾器,然後用它來過濾全表掃描的結果。這與第一個執行計劃IMHO更相似。 – Boneist

+0

@Boneist,我認爲列的行,字節,成本,時間的總值的相似性。令人驚訝的是它們幾乎相同,並且當我們用不同數量的行填充表時發生同步變化:1000,10 000,...,10 000 000 – diziaq

+0

加上一個好的準備好Q.請提供Oracle版本並添加*謂詞信息*給解釋計劃。見[這裏](http://stackoverflow.com/questions/34975406/how-to-describe-performance-issue-in-relational-database?answertab=active#tab-top)如何獲取信息。 –

回答

1

請解釋爲什麼我不能在案件2

你不應該相信優化信任優化計劃。 CBO是95%,但你不知道哪5%是錯的。

典型問題是使用EXPLAIN PLAN顯示的執行計劃不等於執行使用的計劃。 (你不說你如何獲得這個計劃)。

有疑問請使用DBMS_SQLTUNE.REPORT_SQL_MONITOR來查看實際計劃和有問題的零件。

是什麼導致優化器忽略線性和指數複雜度之間的明顯差異?

看到上面,忘了計劃的成本比較。在處理整個表時要避免的是處理NESTED LOOP。 這是情況3

| 3 |  NESTED LOOPS SEMI   |  | 50000| 300000 | 278208956 | 03:01:08| 
| 4 |  TABLE ACCESS FULL   |XTABLE | 1000000| 3000000 |  280 | 00:00:01| 
| 5 |  TABLE ACCESS BY ROWID RANGE |XTABLE | 50000| 150000 |  278 | 00:00:01| 

你想看排序和哈希加入這個是啥子計劃1所示究竟發生了什麼。

在我看來,計劃2將與重複記錄的數量不成比例(簡單地嘗試一個表,每行兩次,看看你是否獲得與案例3相同的經過時間)。 優化程序無法估計重複記錄的數量,因此可以防禦性地估計出高數量,因此成本高。

最後一個備註 - 理論說,你不應該觀察線性特性但充其量O(n * log(n))

最後的評論 - 您的測試數據對於刪除dups不現實。典型的你有一個大的桌子,只有少數幾個人。在你的設置中,除100以外的所有記錄都是dups。

刪除成本占主導地位找到dups的成本,所以你觀察線性行爲。

CREATE TABLE xtable(x) AS 
    SELECT ceil(dbms_random.value * 100000000) 
    FROM dual 
    CONNECT BY level <= 1000000; 

select count(*) total, count(*)- count(distinct x) to_be_deleted from xtable; 
    TOTAL TO_BE_DELETED 
---------- ------------- 
    1000000   5083 

努力讓您將刪除的記錄0.5%。現在規模化,你會完全觀察其他模式。

+0

感謝您提供有用的信息。我同意O(n * log(n)),但令人驚訝的結果是100,000行:1.65秒; 1,000,000行 - 15.8; 10,000,000-138.6秒;甚至比預期的還要低。我認爲低質量的測試數據會抵消常見的理論影響。 – diziaq

+0

@diziaq補充說明 –

1

得到無法重現的第二個計劃。這裏說到:

-------------------------------------------------------------------------------------------          
| Id | Operation    | Name  | Rows | Bytes |TempSpc| Cost (%CPU)| Time  |          
-------------------------------------------------------------------------------------------          
| 0 | DELETE STATEMENT  |   |  |  |  | 3648 (100)|   |          
| 1 | DELETE    | XTABLE |  |  |  |   |   |          
| 2 | MERGE JOIN ANTI NA |   | 999K| 26M|  | 3648 (5)| 00:00:01 |          
| 3 | SORT JOIN   |   | 1000K| 2929K| 22M| 3147 (3)| 00:00:01 |          
| 4 |  TABLE ACCESS FULL | XTABLE | 1000K| 2929K|  | 434 (3)| 00:00:01 |          
|* 5 | SORT UNIQUE   |   | 100 | 2500 |  | 500 (16)| 00:00:01 |          
| 6 |  VIEW    | VW_NSO_1 | 100 | 2500 |  | 499 (16)| 00:00:01 |          
| 7 |  SORT GROUP BY  |   | 100 | 300 |  | 499 (16)| 00:00:01 |          
| 8 |  TABLE ACCESS FULL| XTABLE | 1000K| 2929K|  | 434 (3)| 00:00:01 |          
-------------------------------------------------------------------------------------------   
+0

它看起來像我所期望的。似乎是我的數據庫有一個異常或棘手的設置或別的東西。現在並不重要。困擾我的事情是如何確定DB將執行查詢的方式。我很困惑,因爲之前從未遇到過這樣的問題,並且認爲EXPLAIN PLAN至少近似地顯示了查詢運行時會發生什麼。 – diziaq

+0

@diziaq你有什麼Oracle版本?我已經在11和12測試了它,執行計劃是相同的(當我們不計算成本時)。你將永遠無法確定。您可以使用SQL計劃基線 – Mottor

+0

我昨天和今天多次使用不同的實例在Oracle 12.1上獲得了計劃。在提出這個問題之後,我對Oracle 11.2進行了相同的查詢,並且和您一樣,我無法重現所問的計劃。所以它看起來像一個意外,但我想知道是什麼原因造成的。 – diziaq

相關問題