2014-12-02 80 views
3

數據庫是例如Oracle人力資源數據庫:http://elsasoft.com/samples/oracle/Oracle.XE.HR/default.htm如何創建一個產生這個解釋計劃的查詢? (的Oracle SQL)

解釋計劃:

---------------------------------------------------------- 
| Id | Operation      | Name    | 
---------------------------------------------------------- 
| 0 | SELECT STATEMENT    |     | 
| 1 | HASH UNIQUE     |     | 
|* 2 | TABLE ACCESS BY INDEX ROWID | EMPLOYEES   | 
|* 3 | INDEX RANGE SCAN   | EMP_DEPARTMENT_IX | 
---------------------------------------------------------- 

Predictate Information (identified by operation id): 
---------------------------------------------------- 

2 - filter("MANAGER_ID" < 150) 
3 - access("DEPARTMENT_ID" < 50) 

我嘗試這個查詢,但它產生了非常不同的結果:

select /*+ use_hash(emp) */* 
    from HR.employees emp 
where MANAGER_ID <150 and 
     DEPARTMENT_ID <50; 

我已經建立了filteraccess的where語句。並從HASH_UNIQUEuse_hash。但結果仍然是非常不同的,我不知道如何解決它

+4

的'HASH UNIQUE'指示存在一個'distinct'或可能'by'涉及 – 2014-12-02 11:39:13

+0

我試圖SELECT DISTINCT'EMPLOYEE_ID組'from ...但仍然不是UNIQUE_ID – 2014-12-02 11:52:44

+0

請嘗試像@JonHeller的回答,以區別'first_name'或另一個非索引列。 – 2014-12-08 14:11:20

回答

4

創建一個精確的解釋計劃是困難的,取決於查詢,版本,參數和無證提示。

在這種情況下,主要提示可能是未公開的USE_HASH_AGGREGATION,但它也必須與DISTINCTGROUP BY結合使用。但是它也取決於使用哪個列 - 如果查詢只對主鍵做了明確的分析,那麼它不會聚合,因爲優化器知道沒有必要。

由於我使用12c,我必須禁用_optimizer_batch_table_access_by_rowid,但這對於早期版本不是必需的。

無證件format => '+outline'功能有助於創建精確的計劃。如果你不使用12c,很難保證它能以相同的方式工作。 This SQL Fiddle適用於11gR2,但很難知道提示是否有效,或者計劃是否相同。

查詢

explain plan for 
select 
    /*+ 
     BEGIN_OUTLINE_DATA 
     USE_HASH_AGGREGATION(@"SEL$1") 
     INDEX_RS_ASC(@"SEL$1" "EMP"@"SEL$1" ("EMPLOYEES"."DEPARTMENT_ID")) 
     OUTLINE_LEAF(@"SEL$1") 
     ALL_ROWS 
     OPT_PARAM('_optimizer_batch_table_access_by_rowid' 'false') 
     DB_VERSION('12.1.0.1') 
     OPTIMIZER_FEATURES_ENABLE('12.1.0.1') 
     IGNORE_OPTIM_EMBEDDED_HINTS 
     END_OUTLINE_DATA 
    */ 
    distinct first_name 
from HR.employees emp 
where MANAGER_ID <150 and 
    DEPARTMENT_ID <50; 

計劃

select * from table(dbms_xplan.display(format => 'basic +predicate +outline')); 

Plan hash value: 2074795195 

---------------------------------------------------------- 
| Id | Operation     | Name    | 
---------------------------------------------------------- 
| 0 | SELECT STATEMENT    |     | 
| 1 | HASH UNIQUE     |     | 
|* 2 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES   | 
|* 3 | INDEX RANGE SCAN   | EMP_DEPARTMENT_IX | 
---------------------------------------------------------- 

Outline Data 
------------- 

    /*+ 
     BEGIN_OUTLINE_DATA 
     USE_HASH_AGGREGATION(@"SEL$1") 
     INDEX_RS_ASC(@"SEL$1" "EMP"@"SEL$1" ("EMPLOYEES"."DEPARTMENT_ID")) 
     OUTLINE_LEAF(@"SEL$1") 
     ALL_ROWS 
     OPT_PARAM('_optimizer_batch_table_access_by_rowid' 'false') 
     DB_VERSION('12.1.0.1') 
     OPTIMIZER_FEATURES_ENABLE('12.1.0.1') 
     IGNORE_OPTIM_EMBEDDED_HINTS 
     END_OUTLINE_DATA 
    */ 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    2 - filter("MANAGER_ID"<150) 
    3 - access("DEPARTMENT_ID"<50) 
+1

我通過從員工emp 中選擇不同的姓氏 ,在我的12.1.0.2.0中獲得了期望的計劃,其中manager_id <150 和department_id <50'完全沒有任何提示。我希望不同的first_name可以做同樣的事情,或者實際上可以區分任何非索引列。 – 2014-12-08 14:09:04

2

先試着收集表上的統計,如果上述計劃是有道理的,那麼你會得到它

exec dbms_stats.gather_table_stats('HR','EMP', cascade=>true); 

如果你仍然沒有得到這個計劃,然後甲骨文認爲有一個更好的計劃(他通常是正確的)。 要強制該計劃試圖

select /*+ USE_INDEX(eMP,EMP_DEPARTMENT_IX) */ 
from HR.employees emp 
where MANAGER_ID <150 and DEPARTMENT_ID <50 
+0

謝謝。按索引rowid和索引範圍掃描的表訪問現在在計劃中。只有'HASH UNIQUE'缺失 – 2014-12-02 11:46:26