2012-06-20 87 views
0

在我的一個項目中,我使用dblink對View進行直接查詢,但是在執行檢查後發現它代價高昂(很多嵌套循環,高CPU使用率)。Oracle查詢優化的最佳方式

現在我們已經找到了一個解決方案,即使用函數在視圖上觸發這些查詢。那麼這是正確的解決方案還是有更好的方法來執行此操作。

樣品查詢,有業績報告:

  1. 不使用功能:

查詢:

SELECT t1., 
     t2. 
FROM table1 t1 
     join table2 t2 
     ON t1.id = t2.id 
WHERE t1.bookingId = '0250014547' 

業績報告:

SQL> explain plan for SELECT t1., t2. FROM table1 t1 JOIN table2 t2 ON t1.id = t2.id WHERE t1.bookingId = '0250014547'; 

SQL> select * from table(dbms_xplan.display); 

------------------------------------------------------------------------------------------- 
| Id | Operation      | Name      | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT     |       |  1 | 331 |  6 (0)| 00:00:01 | 
| 1 | NESTED LOOPS     |       |  1 | 331 |  6 (0)| 00:00:01 | 
| 2 | NESTED LOOPS     |       |  1 | 299 |  5 (0)| 00:00:01 | 
| 3 | NESTED LOOPS     |       |  1 | 210 |  4 (0)| 00:00:01 | 
| 4 |  NESTED LOOPS     |       |  1 | 185 |  3 (0)| 00:00:01 | 
| 5 |  NESTED LOOPS    |       |  1 | 156 |  2 (0)| 00:00:01 | 
|* 6 |  TABLE ACCESS BY INDEX ROWID| GENERAL_ACCT_MAST_TABLE |  1 | 66 |  1 (0)| 00:00:01 | 
|* 7 |  INDEX UNIQUE SCAN   | IDX_GAM_FORACID   |  1 |  |  1 (0)| 00:00:01 | 
| 8 |  TABLE ACCESS BY INDEX ROWID| SERVICE_OUTLET_TABLE  | 1694 | 148K|  1 (0)| 00:00:01 | 
|* 9 |  INDEX UNIQUE SCAN   | IDX_SERVICE_OUTLET_TABLE |  1 |  |  1 (0)| 00:00:01 | 
| 10 |  TABLE ACCESS BY INDEX ROWID | GEN_SCHM_PARM_TABLE  | 356 | 10324 |  1 (0)| 00:00:01 | 
|* 11 |  INDEX UNIQUE SCAN   | IDX_GEN_SCHM_PARM_TABLE |  1 |  |  1 (0)| 00:00:01 | 
|* 12 |  TABLE ACCESS BY INDEX ROWID | ACCT_STATEMENT_TABLE  | 12M| 309M|  1 (0)| 00:00:01 | 
|* 13 |  INDEX UNIQUE SCAN   | IDX_ACCT_STATEMENT_TABLE |  1 |  |  1 (0)| 00:00:01 | 
| 14 | TABLE ACCESS BY INDEX ROWID | CUST_MAST_GEN_TABLE  | 24M| 2119M|  1 (0)| 00:00:01 | 
|* 15 |  INDEX UNIQUE SCAN   | IDX_CUST_MAST_GEN_TABLE |  1 |  |  1 (0)| 00:00:01 | 
| 16 | TABLE ACCESS BY INDEX ROWID | BRANCH_BIC_TABLE   | 65258 | 2039K|  1 (0)| 00:00:01 | 
|* 17 | INDEX UNIQUE SCAN    | IDX_BRANCH_BIC_TABLE  |  1 |  |  1 (0)| 00:00:01 | 
------------------------------------------------------------------------------------------- 
  1. 使用功能:

查詢:

SELECT Funquery1('0250014547') 
FROM dual; 

業績報告:

SQL> explain plan for select gtt('0252050014577') from dual; 

SQL> select * from table(dbms_xplan.display); 

----------------------------------------------------------------- 
| Id | Operation  | Name | Rows | Cost (%CPU)| Time  | 
----------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 |  2 (0)| 00:00:01 | 
| 1 | FAST DUAL  |  |  1 |  2 (0)| 00:00:01 | 
----------------------------------------------------------------- 
+0

又是什麼'Funquery1'嗎? – Sathya

+0

它具有相同的查詢,我已經提到上述返回遊標結果。 – Sham

回答

2

是否第二個查詢實際運行速度更快?

通常,SQL優化器不知道在函數內部發生了什麼,函數內部發生的事情並不是查詢計劃的一部分。這意味着您可以隱藏函數內部的大量複雜性,使查詢計劃看起來更有效率。但是,這並不意味着查詢將實際運行得更快,使用更少的CPU,執行更少的I/O操作等。如果您在函數內部放置完全相同的邏輯,則函數執行的查詢將會與原始查詢具有完全相同的計劃。除了幾個額外的PL/SQL到SQL上下文轉換的(小)開銷之外,您將獲得相同的性能。

表格上的統計數據是否準確?查詢計劃中的基數估計是否合理地接近實際? t1.bookingId = '0250014547'謂詞有多選擇性?是bookingID的主鍵t1

您的問題的文本涉及數據庫鏈接,但您發佈的查詢和查詢計劃似乎都不涉及遠程數據庫中的對象。你的問題的文字談到了一個視圖,但你發佈的查詢並沒有引用任何視圖。您發佈的查詢將連接兩個表,查詢計劃將加入7.這些不一致通常會使提供任何建議變得更加複雜。

+0

(賈斯汀)感謝您的信息。由於現在我們正在使用UAT服務器而不是生產服務器,所以你不會找到任何DBLINK,鑑於上面的查詢,但在現實的查詢使用dblink的意見被炒魷魚。這裏的預訂ID是PRIMARY KEY。 – Sham

0

賈斯廷(+1)是完全正確的。 EXPLAIN PLAN向您顯示對函數的調用,並沒有向您顯示函數內發生的任何事情。

在sqlplus,使用

set autotrace on 

這會給你的語句執行的實際統計數據,包括任何遞歸SQL,這是不是在解釋計劃輸出顯示。

對於更高級的調整,你可以使用Oracle跟蹤事件10046.但是sqlplus的「自動跟蹤」可能足以滿足您的需要。

涉及遠程數據庫表/視圖(通過DB_LINK)調整報表可能會很麻煩,因爲你必須要調整既您提交的聲明,並將其發送到遠程數據庫中的語句。