天天看點

Explain Plan試分析

注:以下是本人對Explain Plan的試分析,有不對的地方希望大家指出。關于如何檢視Oracle的解釋計劃請參考: 

例一:

執行的SQL語句:

EXPLAIN plan for
select * from hy_emp emp,hy_dept dept
where emp.deptno=dept.deptno and emp.empno=1

select * from table(dbms_xplan.display)      
Explain Plan試分析

首先執行#3,在HY_EMP表進行empno=1的查找(索引唯一掃描方式);

再執行#5,在HY_DEPT表進行emp.deptno=dept.deptno的連接配接(索引唯一掃描方式);

然後,把兩個結果集進行嵌套循環連接配接;

最後,把select子句裡的字段帶上。

例二:

EXPLAIN plan for

select * from hy_emp emp,hy_dept dept
where emp.deptno=dept.deptno and emp.ename='Andy'

select * from table(dbms_xplan.display)      

截圖:

Explain Plan試分析

分析:

#9先執行,在emp表進行NAME=Andy的篩選,不要的資料丢棄(ENAME不是emp表的主鍵);

#10第二執行,在emp表查找DEPTNO能與DEPT表對應上的記錄(直接去取ACCESS方式,因為DEPTNO是DEPT表的主鍵);

#8第三執行,将#9,#10兩步得到的結果集(兩者都是EMP表的子集)進行嵌套循環連接配接;

接下來,将#8得到的結果集與#11進行嵌套循環連接配接(直接去取ACCESS方式,因為DEPTNO是DEPT表的主鍵)

最後執行#6,把select子句都帶出來。

例三:

SQL:

EXPLAIN plan for

select emp.* from hy_emp emp,hy_dept dept
where emp.deptno=dept.deptno and emp.ename='Andy'

select * from table(dbms_xplan.display)      
Explain Plan試分析

解讀:

#8先執行,在emp表進行NAME=Andy的篩選,不要的資料丢棄(ENAME不是emp表的主鍵);

#9第二執行,在emp表查找DEPTNO能與DEPT表對應上的記錄(直接去取ACCESS方式,因為DEPTNO是DEPT表的主鍵)

#7再執行,将#8,#9兩步得到的結果集(均為emp的子集)進行嵌套循環連接配接;

由于select子句中隻要emp表的字段,是以#7得到的結果集就是最終結果集;

最後把select子句中字段都帶出來。

這一段也印證了前面關于 “#8,#9兩步得到的結果集均為emp的子集” 的論斷。

 例四:

EXPLAIN plan for

select dept.* from hy_emp emp,hy_dept dept
where emp.deptno=dept.deptno and emp.ename='Andy'

select * from table(dbms_xplan.display)      
Explain Plan試分析

#10第二執行,在emp表查找DEPTNO能與DEPT表對應上的記錄(直接去取ACCESS方式,因為DEPTNO是DEPT表的主鍵)

#8再執行,将#9,#10兩步得到的結果集(均為emp的子集)進行嵌套循環連接配接;

由于select子句中需要dept表的字段,是以#8得到的結果集因為隻是emp的子集不足以提供dept表的字段,還需要與dept表做一次連接配接;

#7執行,将#11得到的結果集(dept表的子集)與#8結果集進行嵌套循環連接配接;

最後帶上select子句的字段。

例五:

EXPLAIN plan for

select count(*) from hy_emp emp,hy_dept dept
where emp.deptno=dept.deptno and emp.ename='Andy'

select * from table(dbms_xplan.display)      
Explain Plan試分析

#9,#10,#8的分析和前面的同類語句類似;

因最終不需要dept表的資料,是以得到#8的結果集就夠count(×)的統計了;

#7 的sort aggregate是排序聚合的意思,但這并非動作,而是代表語句類型,從cost看它也未産生消耗;

最後把select子句帶出來就夠了。

例六:

SQL:

EXPLAIN plan for

select * from hy_emp emp,hy_dept dept
where emp.deptno=dept.deptno and emp.ename like '%in%'
order by emp.empno

select * from table(dbms_xplan.display)      
Explain Plan試分析

從縮進層次裡來看,#10先執行,這一步走的是emp表的按empno排序(索引全掃描方式) ;

#9之後執行,在emp表進行NAME  like ‘%in%’的篩選,不要的資料丢棄(ENAME不是emp表的主鍵);

#11再執行,在emp表查找DEPTNO能與DEPT表對應上的記錄(直接去取資料(ACCESS方式),因為DEPTNO是DEPT表的主鍵)

因為是select *,#8得到的結果集不足以成為最終結果集,它還要與dept表進行連接配接(從#8結果集找出deptno直接到dept中去找)

最後把select子句帶出來。

CREATE TABLE hy_emp
(
    empno NUMBER(8,0) not null primary key,
    ename NVARCHAR2(60) not null,
    deptno NUMBER(8,0) not null,
    sal NUMBER(10,0) DEFAULT 0 not null 
)


CREATE TABLE hy_dept
(
    deptno NUMBER(8,0) not null primary key,
    dname NVARCHAR2(60) not null
)      
insert into hy_dept(deptno,dname) values('1','Hr');
insert into hy_dept(deptno,dname) values('2','Dev');
insert into hy_dept(deptno,dname) values('3','Qa');
insert into hy_dept(deptno,dname) values('4','Sales');
insert into hy_dept(deptno,dname) values('5','Mng');

insert into hy_emp(empno,ename,deptno,sal) values('1','Andy','1',1000);
insert into hy_emp(empno,ename,deptno,sal) values('2','Bill','2',2000);
insert into hy_emp(empno,ename,deptno,sal) values('3','Cindy','3',3000);
insert into hy_emp(empno,ename,deptno,sal) values('4','Douglas','4',4000);
insert into hy_emp(empno,ename,deptno,sal) values('5','Edinburg','5',5000);
insert into hy_emp(empno,ename,deptno,sal) values('6','Felix','1',6000);
insert into hy_emp(empno,ename,deptno,sal) values('7','Hellen','2',7000);
insert into hy_emp(empno,ename,deptno,sal) values('8','Isis','3',8000);
insert into hy_emp(empno,ename,deptno,sal) values('9','Jean','4',9000);
insert into hy_emp(empno,ename,deptno,sal) values('10','King','5',10000);
insert into hy_emp(empno,ename,deptno,sal) values('11','Mac','1',11000);