注:以下是本人對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)
首先執行#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)
截圖:
分析:
#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)
解讀:
#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)
#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)
#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)
從縮進層次裡來看,#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);