2016-09-14 51 views
1

3表:僱員(emp_id,dept_id,job_id,emp_fname,emp_lname,工資,地址,電子郵件),部門(dept_id,d_name)和工作(job_id,j_title)。*在oracle的解釋計劃的某些步驟旁邊有什麼意思?

僱員(emp_id),部門(dept_id)和工作(job_id)上的非唯一索引。

SQL> explain plan for 
select d.d_name, j.j_title, count(1) 
from employees e join departments d on e.dept_id=d.dept_id 
join jobs j on e.job_id=j.job_id 
where e.salary>30000 
group by d.d_name, j.j_title; 

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

---------------------------------------------------------------------------------- 

| Id |操作|名稱|行|字節|成本(%CPU)|時間|

------------------------------------------------------------------------------------------------ 
| 0 | SELECT STATEMENT | | 10 | 890 | 4 (25)| 00:00:01 | 
| 1 | HASH GROUP BY | | 10 | 890 | 4 (25)| 00:00:01 | 
| 2 |  NESTED LOOPS | | | | | | 
| 3 |  NESTED LOOPS | | 10 | 890 | 3 (0)| 00:00:01 | 
| 4 |   NESTED LOOPS | | 10 | 640 | 3 (0)| 00:00:01 | 
|* 5 |   TABLE ACCESS FULL | EMPLOYEES | 10 | 390 | 3 (0)| 00:00:01 | 
| 6 |   TABLE ACCESS BY INDEX ROWID| JOBS | 1 | 25 | 0 (0)| 00:00:01 | 
|* 7 |   INDEX RANGE SCAN | JOBS_JOB_ID | 1 | | 0 (0)| 00:00:01 | 
|* 8 |  INDEX RANGE SCAN | DEPT_DEPT_ID | 1 | | 0 (0)| 00:00:01 | 
| 9 |  TABLE ACCESS BY INDEX ROWID | DEPARTMENTS | 1 | 25 | 0 (0)| 00:00:01 | 

謂詞信息(由操作ID標識): --------------------------------- ------------------

5 - filter("E"."SALARY">30000) 

7 - access("E"."JOB_ID"="J"."JOB_ID") 

8 - access("E"."DEPT_ID"="D"."DEPT_ID") 

-------------------------------------------------------------------------- 
  1. 是什麼步驟5,7和9 *是什麼意思?
  2. 這裏有3個嵌套循環的作用是什麼?
  3. 步驟7和步驟6在同一個循環中。當他們做類似的工作時,爲什麼步驟8和9處於不同的循環中?
  4. 任何人都可以請解釋我每一步做什麼?
+1

這些指的是有關計劃下應該出現的那些步驟的其他優化程序的註釋。 –

+0

您能否詳細說明一下? @JeffreyKemp –

+0

您還沒有將整個解釋計劃複製到您的問題中。修改您的問題以提供缺失的信息,也許我們可以幫助您。 –

回答

2

正如傑弗裏提到的,這些是關於執行計劃的一些額外信息。他們通常出現where/like(etc)條件和HASH JOINS(可能是其他但我不確定)。基本上,優化者希望你提供額外的信息,這些信息不能放在解釋計劃的輸出中。

您可以通過下面的運行自行復制它。

EXPLAIN PLAN FOR 
your_query; 

然後運行

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); 

輸出(在我的情況)

----------------------------------------------------------------------------------- 
| Id | Operation  | Name   | Rows | Bytes | Cost (%CPU)| Time  | 
----------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |    | 17 | 187 |  2 (0)| 00:00:01 | 
|* 1 | INDEX RANGE SCAN| EMP_DATA_ENAME | 17 | 187 |  2 (0)| 00:00:01 | 
----------------------------------------------------------------------------------- 

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

    1 - access("ENAME" LIKE 'ZM%') 
     filter("ENAME" LIKE 'ZM%') 
1
| 4 |   NESTED LOOPS | | 10 | 640 | 3 (0)| 00:00:01 | 
|* 5 |   TABLE ACCESS FULL | EMPLOYEES | 10 | 390 | 3 (0)| 00:00:01 | 
5 - filter("E"."SALARY">30000) 

EMPLOYEES表中的所有行將被查詢,並且這些給定的過濾器匹配的上SALARY將被髮送到計劃的下一步。

| 6 |   TABLE ACCESS BY INDEX ROWID| JOBS | 1 | 25 | 0 (0)| 00:00:01 | 
|* 7 |   INDEX RANGE SCAN | JOBS_JOB_ID | 1 | | 0 (0)| 00:00:01 | 
7 - access("E"."JOB_ID"="J"."JOB_ID") 

從步驟5發出的每一行都包含僱員的JOB_ID。索引JOBS_JOB_ID將被探測(步驟7)此JOB_ID,並且ROWID將被用於從JOBS表中檢索對應的行(步驟6)。

| 3 |  NESTED LOOPS | | 10 | 890 | 3 (0)| 00:00:01 | 
|* 8 |  INDEX RANGE SCAN | DEPT_DEPT_ID | 1 | | 0 (0)| 00:00:01 | 
8 - access("E"."DEPT_ID"="D"."DEPT_ID") 

EMPLOYEES表(先前在步驟5中檢索)的DEPT_ID現在用於探測DEPT_DEPT_ID索引(步驟8)。

| 2 |  NESTED LOOPS | | | | | | 
| 9 |  TABLE ACCESS BY INDEX ROWID | DEPARTMENTS | 1 | 25 | 0 (0)| 00:00:01 | 

DEPT_DEPT_ID指數ROWID現在用於檢索部門表中的行。

| 0 | SELECT STATEMENT | | 10 | 890 | 4 (25)| 00:00:01 | 
| 1 | HASH GROUP BY | | 10 | 890 | 4 (25)| 00:00:01 | 

結果被放入一個哈希表(使用基於d.d_name + j.j_title的關鍵),因爲它去計算每個記錄。當檢索到最後一條記錄時,掃描散列表以返回每個d_name,j_title的計數。

+0

非常感謝! :) 你能否告訴我,步驟7和步驟6是在同一個循環中。當他們做類似的工作時,爲什麼步驟8和9處於不同的循環中? –

+0

沒有特別的理由 - 解釋計劃只是優化器的調試輸出,並且有它的怪癖。有時您可能會從類似的執行計劃中獲得略微不同的模式 –