溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Oracle里另外一些典型的執(zhí)行計(jì)劃

發(fā)布時(shí)間:2020-05-27 00:46:40 來(lái)源:網(wǎng)絡(luò) 閱讀:923 作者:hbxztc 欄目:關(guān)系型數(shù)據(jù)庫(kù)

在之前的文章里寫(xiě)了Oracle里常見(jiàn)的執(zhí)行計(jì)劃,可以參考文章:http://hbxztc.blog.51cto.com/1587495/1901416,這篇文章里介紹的是其他的一些典型的執(zhí)行計(jì)劃。

1. AND-EQUAL(INDEX MERGE)

AND-EQUAL又稱(chēng)為INDEX MERGE,顧名思義,INDEX MERGE就是指如果where條件里出現(xiàn)了多個(gè)針對(duì)不同單列的等值條件,并且這些列上都有單鍵值的索引,則Oracle可能會(huì)以相應(yīng)的單個(gè)等值條件去分別掃描這些索引;然后Oracle會(huì)合并這些掃描單個(gè)索引所得到的rowid集合,如果能從這些集合中找到相同的rowid,那么這個(gè)rowid就是目標(biāo)SQL最終執(zhí)行結(jié)果所對(duì)應(yīng)的rowid。最后,Oracle只需要用這些rowid回表就能得到目標(biāo)SQL的最終執(zhí)行結(jié)果。

AND-EQUAL在執(zhí)行計(jì)劃中對(duì)應(yīng)的關(guān)鍵字就是“AND-EQUAL”,我們可以使用Hint來(lái)強(qiáng)制讓Oracle走AND-EQUAL。

看一個(gè)實(shí)例:

zx@MYDB>create table emp_temp as select * from scott.emp;

Table created.

zx@MYDB>create index idx_mgr on emp_temp(mgr);

Index created.

zx@MYDB>create index idx_deptno on emp_temp(deptno);

Index created.

zx@MYDB>select /*+ and_equal(emp_temp idx_mgr idx_deptno) */ empno,job from emp_temp where mgr=7902 and deptno=20;

     EMPNO JOB
---------- ---------------------------
      7369 CLERK

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容中可以看出,現(xiàn)在此SQL的執(zhí)行計(jì)劃走的是對(duì)索引IDX_MGR和IDX_DEPTNO的AND-EQUAL。

2. INDEX JOIN

INDEX JOIN很容易引起誤解,因?yàn)樗⒉皇侵竿ǔR饬x上針對(duì)多表的表連接。這里INDEX JOIN指的是針對(duì)單表上的不同索引之間的連接。

還以上面的EMP_TEMP為例,已經(jīng)在列MGR和DEPTNO上分別創(chuàng)建了兩個(gè)單鍵值的B*Tree索引,如果此時(shí)執(zhí)行SQL語(yǔ)句“select mgr,deptno from emp_temp”,因?yàn)檫@里要查詢的列MGR和DEPTNO均可來(lái)源于索引IDX_MGR和IDX_DEPTNO(不考慮NULL值),不用回表,所以除了常規(guī)的執(zhí)行方法之外,Oracle還可以采用如下方法:分別掃描索引IDX_MGR和IDX_DEPTNO,得到的結(jié)果集分別記為結(jié)果集1和結(jié)果集2,然后將結(jié)果集1和2做一個(gè)連接,連接條件就是“結(jié)果集1.rowid=結(jié)果集2.rowid”,這樣得到的最終連接結(jié)果(不用回表)就是上述SQL的執(zhí)行結(jié)果。

很顯然,針對(duì)上述SQL的INDEX JOIN的執(zhí)行效率是不如我們直接在列MGR和DEPTNO上建一個(gè)組合索引,然后直接掃描該組全索引的效率高。INDEX JOIN只是為CBO提供了一種可選的執(zhí)行路徑,大多數(shù)情況下,它只是額外多出的一種選擇而已。

看一下例子:

zx@MYDB>delete from emp_temp where mgr is null;

1 row deleted.

zx@MYDB>commit;

Commit complete.

zx@MYDB>alter table emp_temp modify mgr not null;

Table altered.

zx@MYDB>alter table emp_temp modify deptno not null;

Table altered.

zx@MYDB>select mgr,deptno from emp_temp;

       MGR     DEPTNO
---------- ----------
      7839         10
......
      7698         30

13 rows selected.

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容可以看出,現(xiàn)在目標(biāo)SQL的執(zhí)行計(jì)劃走的是對(duì)索引IDX_MGR和IDX_DEPTNO的HASH JOIN。

3. VIEW

Oracle在處理包含視圖的SQL時(shí),根據(jù)該視圖是否能做為視圖合并(View Merging),其對(duì)應(yīng)的執(zhí)行計(jì)劃有如下兩種形式。

  • 如果可以做視圖合并,則Oracle在執(zhí)行該SQL時(shí)可以直接針對(duì)該視圖的基表,此時(shí)SQL的執(zhí)行計(jì)劃中很可能不會(huì)出現(xiàn)關(guān)鍵字“VIEW”(不能完全依賴(lài)關(guān)鍵字“VIEW”的出現(xiàn)與否來(lái)判斷Oracle是否做了視圖合并,因?yàn)閷?duì)于某些SQL而言,即使Oracle已經(jīng)做了視圖合并但其所對(duì)應(yīng)的執(zhí)行計(jì)劃中可能還會(huì)顯示關(guān)鍵字“VIEW”)。

  • 如果不能做視圖合并,則Oracle將把該視圖看作一個(gè)整體并獨(dú)立地執(zhí)行它,此時(shí)SQL的執(zhí)行計(jì)劃中將會(huì)出現(xiàn)關(guān)鍵字“VIEW”。

看一個(gè)實(shí)例,還是使用上面的EMP_TEMP表:

zx@MYDB>create view emp_mgr_view as select * from emp_temp where job='MANAGER';

View created.

zx@MYDB>select empno,sal from emp_mgr_view where ename='CLARK';

     EMPNO        SAL
---------- ----------
      7782       2450

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容中可以看出,現(xiàn)在SQL的執(zhí)行計(jì)劃走的是對(duì)表EMP_TEMP的全表掃描,并且全表掃描進(jìn)的過(guò)濾查詢條件是filter(("ENAME"='CLARK' AND "JOB"='MANAGER')).顯然這里Oracle做了視圖合并,直接查詢的視圖EMP_MGR_VIEW的基表EMP_TEMP,并且把針對(duì)視圖的where條件推到了視圖的內(nèi)部,和原先創(chuàng)建視圖時(shí)的限制條件做了合并。

現(xiàn)在修改視圖EMP_MGR_VIEW的定義,其創(chuàng)建語(yǔ)句中加入ROWNUM關(guān)鍵字,這樣新創(chuàng)建的同名視圖EMP_MGR_VIEW將不能再做視圖合并:

zx@MYDB>create or replace view emp_mgr_view as select * from emp_temp where job='MANAGER' and rownum<10;

View created.

zx@MYDB>select empno,sal from emp_mgr_view where ename='CLARK';

     EMPNO        SAL
---------- ----------
      7782       2450

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容中可以看出,現(xiàn)在該SQL的執(zhí)行計(jì)劃中包含了關(guān)鍵字“VIEW”,即表明這里Oracle并沒(méi)有對(duì)視圖EMP_MGR_VIEW做視圖合并,視圖EMP_MGR_VIEW被Oracle當(dāng)作一個(gè)整體來(lái)獨(dú)立執(zhí)行。

4. FILTER

FILTER直譯過(guò)來(lái)就是過(guò)濾、篩選的意思,它是一種特殊的執(zhí)行計(jì)劃,所對(duì)應(yīng)的執(zhí)行過(guò)程就是如下三步:

得到一個(gè)驅(qū)動(dòng)結(jié)果集

根據(jù)一定的過(guò)濾條件從上述驅(qū)動(dòng)結(jié)果集中濾除不滿足條件的記錄

結(jié)果集中剩下的記錄就會(huì)返回給最終用戶或者繼續(xù)參與一下個(gè)執(zhí)行步驟。

看一個(gè)實(shí)例,還是使用上面的視圖EMP_MGR_VIEW:

zx@MYDB>select empno,ename from emp where empno in (select empno from emp_mgr_view);

     EMPNO ENAME
---------- ------------------------------
      7566 JONES
      7698 BLAKE
      7782 CLARK

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述的顯示內(nèi)容可以看出,現(xiàn)在該SQL的執(zhí)行計(jì)劃走的是嵌套循環(huán)連接,并沒(méi)有出現(xiàn)我們希望的FILTER類(lèi)型的執(zhí)行計(jì)劃。這是因?yàn)镺racle在這里做了子查詢展開(kāi)(Subquery Unnexting),即把子查詢和它外部的SQL做了合并,轉(zhuǎn)化成視圖VW_NOS_1和表EMP做連接。

這里使用Hint禁掉子查詢展開(kāi)后重新執(zhí)行上述SQL:

zx@MYDB>select empno,ename from emp where empno in (select /*+ NO_UNNEST */ empno from emp_mgr_view);

     EMPNO ENAME
---------- ------------------------------
      7566 JONES
      7698 BLAKE
      7782 CLARK

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容中可以看出,現(xiàn)在該SQL走的就是我們希望的FILTER類(lèi)型執(zhí)行計(jì)劃。

FILTER類(lèi)型的執(zhí)行計(jì)劃實(shí)際上是種改良的嵌套循環(huán)連接,它并不像嵌套循環(huán)連接那樣,驅(qū)動(dòng)結(jié)果集中的有多少記錄就得訪問(wèn)多少次被驅(qū)動(dòng)表。

用一個(gè)實(shí)驗(yàn)驗(yàn)證:

zx@MYDB>select * from t1;

      COL1 COL2
---------- ----
         1 A
         2 B
         3 B

zx@MYDB>select * from t2;

COL2 COL3
---- ------
A    A2
B    B2
D    D2

zx@MYDB>select /*+ gather_plan_statistics */ * from t1 where col2 in(select /*+ no_unnest */ col2 from t2);

      COL1 COL2
---------- ----
         1 A
         2 B
         3 B

Oracle里另外一些典型的執(zhí)行計(jì)劃

注意到上述顯示內(nèi)容中id=2的執(zhí)行步驟所對(duì)應(yīng)的列A-Rows的值為3,id=3的執(zhí)行步驟所對(duì)應(yīng)的列Starts的值為2,說(shuō)明雖然全表掃描T1所得到的驅(qū)動(dòng)結(jié)果集的數(shù)量為3,但走Filter類(lèi)型的執(zhí)行計(jì)劃時(shí)訪問(wèn)被驅(qū)動(dòng)表T2的實(shí)際次數(shù)卻不是3,而是2.這是因?yàn)楸鞹數(shù)量雖然是3,但其列COL2的distinct值的數(shù)量卻只有2,所以在用過(guò)濾條件“where col2 in(select /*+ no_unnest */ col2 from t2)”去過(guò)濾表T1中的數(shù)據(jù)時(shí),只用訪問(wèn)兩次表T2就可以了。

5. SORT

SORT就是排序的意思,執(zhí)行計(jì)劃中的SORT通常會(huì)以組合的方式出現(xiàn),這些組合方式包括但不限于如下這幾種:

  • SORT AGGREGATE

  • SORT UNIQUE

  • SORT JOIN

  • SORT GROUP BY 

  • SORT ORDER BY

  • BUFFER SORT

執(zhí)行計(jì)劃中即使出現(xiàn)了關(guān)鍵字“SORT”,也不一定意味著就需要排序,比如SORT AGGREGATE和BUFFER SORT就不一定需要排序。

看一個(gè)實(shí)例,還是使用上面的EMP_TEMP表:

zx@MYDB>set autotrace traceonly
zx@MYDB>select sum(sal) from emp_temp where job='MANAGER';

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容可以看出,現(xiàn)在SQL的執(zhí)行計(jì)劃走的是SORT AGGREGATE,這里執(zhí)行的SQL只是求了一個(gè)sum值,很顯然這里不需要排序的。統(tǒng)計(jì)信息中的sort(memroy)和sort(disk)的值均為0,也說(shuō)明Oracle在執(zhí)行此SQL時(shí)并沒(méi)有做任何排序操作,所以我們說(shuō)SORT AGGREGATE并不一定需要排序,這其中的關(guān)鍵字“SORT”具有一定的迷惑性。

下面再做實(shí)例:

zx@MYDB>set autotrace off
zx@MYDB>select distinct ename from emp_temp where job='MANAGER' order by ename;

ENAME
------------------------------
BLAKE
CLARK
JONES

上述SQL的含義是既要排序又要去重,它對(duì)應(yīng)的執(zhí)行計(jì)劃就會(huì)是SORT UNIQUE

Oracle里另外一些典型的執(zhí)行計(jì)劃

zx@MYDB>select /*+ use_merge(t1 t2) */t1.empno,t1.ename,t2.sal from scott.emp t1,emp_temp t2 where t1.empno=t2.empno;

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容中可以看出,現(xiàn)在該SQL的執(zhí)行計(jì)劃走的是對(duì)EMP和EMP_TEMP的排序合并連接。SORT JOIN類(lèi)型的執(zhí)行計(jì)劃通常會(huì)出現(xiàn)在排序合并連接中,它是排序合并連接所對(duì)應(yīng)的執(zhí)行計(jì)劃第一步要做的事情。

再執(zhí)行如下SQL:

zx@MYDB>select ename from emp_temp where job='MANAGER' order by ename;

ENAME
------------------------------
BLAKE
CLARK
JONES

上述SQL的含義是只需要單純的排序,它對(duì)應(yīng)的執(zhí)行計(jì)劃就會(huì)是SORT ORDER BY:

Oracle里另外一些典型的執(zhí)行計(jì)劃

接著執(zhí)行下面的SQL:

select ename from emp_temp where job='MANAGER' group by ename order by ename;

ENAME
------------------------------
BLAKE
CLARK
JONES

上述SQL的含義是既要排序又要分組,所以它對(duì)應(yīng)的執(zhí)行計(jì)劃就會(huì)是SORT GROUP BY:

Oracle里另外一些典型的執(zhí)行計(jì)劃

最后執(zhí)行如下SQL:

select t1.empno,t2.ename from scott.emp t1,emp_temp t2;

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容可以看出,現(xiàn)在該SQL的執(zhí)行計(jì)劃走的是對(duì)表EMP_TEMP和表EMP上主鍵PK_EMP的笛卡兒連接,因?yàn)樯鲜鯯QL中沒(méi)有指定連接條件。此處執(zhí)行計(jì)劃的步驟是首先全表掃描表EMP_TEMP,掃描結(jié)果記為結(jié)果集1;接著對(duì)表EMP上的主鍵PK_EMP做索引快速全掃描,并將掃描結(jié)果load進(jìn)PGA中,然后對(duì)結(jié)果集1和結(jié)果集2做笛卡兒連接,最后笛卡兒連接的結(jié)果就是上述SQL的最終執(zhí)行結(jié)果。執(zhí)行計(jì)劃中關(guān)鍵字“BUFFER SORT”就是表示Oracle會(huì)借用PGA并把掃描結(jié)果load進(jìn)去,這樣做的好處是省掉了相應(yīng)的緩存在SGA中所帶來(lái)的種種額外開(kāi)銷(xiāo)(如持有、釋放相關(guān)Latch等)。PGA常常用來(lái)做排序,這可能就是“BUFFER SORT”中關(guān)鍵字SORT的由來(lái)。

需要注意的是,BUFFER SORT不一定會(huì)排序,也可能會(huì)排序,也可能不會(huì)。

看一個(gè)SQL是否排序,最直觀的方法就是查看其統(tǒng)計(jì)信息中"sorts(memory)"和"sorts(disk)"的值,如果這兩個(gè)指標(biāo)的值大于0,則說(shuō)明該SQL在執(zhí)行時(shí)經(jīng)歷過(guò)排序。但遺憾的是,這兩個(gè)指標(biāo)對(duì)BUFFER SORT而言是不準(zhǔn)的,此時(shí)我們就需要借助目標(biāo)SQL真實(shí)執(zhí)行計(jì)劃中"Column Projection Information"部分"keys"的值來(lái)判斷到底所對(duì)應(yīng)的BUFFER SORT有沒(méi)有排序。"#keys"的值就表示該執(zhí)行步驟實(shí)際排序列的數(shù)量,如果"#keys"值大于0時(shí),則表示該執(zhí)行步驟確實(shí)排過(guò)序了。

看如下SQL:

set autotrace traceonly
zx@MYDB>select t1.ename,t2.loc from scott.emp t1,scott.dept t2;

56 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 2034389985

-----------------------------------------------------------------------------
| Id  | Operation	     | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |	    |	 56 |	784 |	 10   (0)| 00:00:01 |
|   1 |  MERGE JOIN CARTESIAN|	    |	 56 |	784 |	 10   (0)| 00:00:01 |
|   2 |   TABLE ACCESS FULL  | DEPT |	  4 |	 32 |	  3   (0)| 00:00:01 |
|   3 |   BUFFER SORT	     |	    |	 14 |	 84 |	  7   (0)| 00:00:01 |
|   4 |    TABLE ACCESS FULL | EMP  |	 14 |	 84 |	  2   (0)| 00:00:01 |
-----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
	315  recursive calls
	  0  db block gets
	 70  consistent gets
	 11  physical reads
	  0  redo size
       1831  bytes sent via SQL*Net to client
	557  bytes received via SQL*Net from client
	  5  SQL*Net roundtrips to/from client
	  7  sorts (memory)
	  0  sorts (disk)
	 56  rows processed

注意到上述顯示內(nèi)容中“統(tǒng)計(jì)信息”部分的sorts(memory)的值為7,但由于該SQL中出現(xiàn)了ID=3的執(zhí)行步驟“BUFFER SORT”,所以這并不一定能說(shuō)明該SQL在執(zhí)行時(shí)經(jīng)歷過(guò)排序。

我們來(lái)看一下執(zhí)行墳?zāi)怪衖d=3的執(zhí)行步驟“BUFFER SORT”所對(duì)應(yīng)的“#keys”的值:

zx@MYDB>select sql_id,sql_text from v$sql where sql_text = 'select t1.ename,t2.loc from scott.emp t1,scott.dept t2';

SQL_ID		     SQL_TEXT
-------------------- ----------------------------------------------------------------------------------------------------
3dmxcxk72fwr4	     select t1.ename,t2.loc from scott.emp t1,scott.dept t2

zx@MYDB>select * from table(dbms_xplan.display_cursor('3dmxcxk72fwr4',0,'advanced'));

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容中可以看出,Id=3的執(zhí)行步驟“BUFFER SORT”所對(duì)應(yīng)的“#keys”的值為0,說(shuō)明該SQL在執(zhí)行“BUFFER SORT”時(shí)確實(shí)沒(méi)有排序,排序的數(shù)量為0。

這就驗(yàn)證了我們之前提到的觀點(diǎn):統(tǒng)計(jì)信息中sorts(memory)和sorts(disk)的值對(duì)于BUFFER SORT而言是不準(zhǔn)的,Oracle在執(zhí)行BUFFER SORT時(shí)可能不需要排序。

6. UNION/UNION ALL

UNION/UNION ALL表示對(duì)兩個(gè)結(jié)果集進(jìn)行合并,如果它們出現(xiàn)在執(zhí)行計(jì)劃中也表示相同的含義。

UNION和UNION ALL的區(qū)別是:UNION ALL僅僅是簡(jiǎn)單地將兩個(gè)結(jié)果集合并,并不做任何額外的處理;而UNION除了將兩個(gè)結(jié)果集簡(jiǎn)單合并之外,還會(huì)對(duì)合并后的結(jié)果集做排序和去重,即UNION相當(dāng)于先做UNION ALL,然后再對(duì)UNION ALL之后的結(jié)果集做SORT UNIQUE

看一個(gè)實(shí)例:

select empno,ename from scott.emp union all select empno,ename from emp_temp;

     EMPNO ENAME
---------- ------------------------------
      7369 SMITH
......
      7934 MILLER

27 rows selected.

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容中可以看出,現(xiàn)在該SQL的執(zhí)行計(jì)劃走的是對(duì)表EMP和EMP_TEMP全表掃描后的結(jié)果集的UNION ALL,UNION ALL在執(zhí)行計(jì)劃中對(duì)應(yīng)的關(guān)鍵字就是UNION-ALL。表EMP有13條記錄,表EMP_TEMP有12條記錄,UNION ALL合并后的結(jié)果集總是25。

把UNION ALL改為UNION:

zx@MYDB>select empno,ename from scott.emp union select empno,ename from emp_temp;

     EMPNO ENAME
---------- ------------------------------
      7369 SMITH
......
      7934 MILLER

14 rows selected.

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容可以看出,現(xiàn)在該SQL的執(zhí)行計(jì)劃走的是對(duì)EMP和EMP_TEMP全表掃描的結(jié)果集的UNION,UNION在執(zhí)行計(jì)劃中對(duì)應(yīng)的關(guān)鍵字就是"UNION-ALL"和"SORT UNIQUE",即表示UNION相當(dāng)于在UNION ALL的基礎(chǔ)上做排序和去重。表EMP_TEMP的數(shù)據(jù)全部來(lái)源于表EMP,所以這里UNION操作返回結(jié)果集的復(fù)數(shù)就是表EMP的行數(shù)14。

7. CONCAT

CONCAT就是IN-List擴(kuò)展(IN-List Expansion)或OR擴(kuò)展(OR Expansion),IN-List擴(kuò)展/OR擴(kuò)展在執(zhí)行計(jì)劃中對(duì)應(yīng)的關(guān)鍵字是“CONCATENATION”,使用Hint來(lái)強(qiáng)制讓Oracle走IN-List擴(kuò)展/OR擴(kuò)展。

看一下實(shí)例:

zx@MYDB>select empno,ename from scott.emp where empno in (7654,7698,7782);

     EMPNO ENAME
---------- ------------------------------
      7654 MARTIN
      7698 BLAKE
      7782 CLARK

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容可以看出,現(xiàn)在該SQL的執(zhí)行計(jì)劃走的是對(duì)表EMP和主鍵索引PK_EMP的IN-List迭代。

使用Hint讓Oracle強(qiáng)制走IN-List擴(kuò)展

zx@MYDB>select /*+ USE_CONCAT */empno,ename from scott.emp where empno in (7654,7698,7782);

     EMPNO ENAME
---------- ------------------------------
      7654 MARTIN
      7698 BLAKE
      7782 CLARK

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上面顯示內(nèi)容可以看出,Hint失效了,還是走IN-List迭代。使用如下兩個(gè)事件在當(dāng)前Session中將IN-List迭代禁掉,并將輸入?yún)?shù)no_invalidate的值設(shè)為false后重新收集一下統(tǒng)計(jì)信息,以便后續(xù)再次執(zhí)行上述SQL時(shí)不會(huì)沒(méi)用之前走IN-List迭代的執(zhí)行計(jì)劃:

zx@MYDB>alter session set events '10142 trace name context forever';

Session altered.

zx@MYDB>alter session set events '10157 trace name context forever';

Session altered.

zx@MYDB>exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'EMP',cascade=>true,method_opt=>'for all columns size 1',no_invalidate=>false);

PL/SQL procedure successfully completed.

zx@MYDB>select /*+ USE_CONCAT */ empno,ename from scott.emp where empno in (7654,7698,7782);

     EMPNO ENAME
---------- ------------------------------
      7654 MARTIN
      7698 BLAKE
      7782 CLARK

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容中可以看出,現(xiàn)在該SQL的執(zhí)行計(jì)劃變成了我們想要的IN-List擴(kuò)展,在執(zhí)行計(jì)劃中對(duì)應(yīng)的關(guān)鍵字就是CONCATENATION。這里CONCATENATION的含義就相當(dāng)于UNION ALL,即上述SQL就相當(dāng)于UNION ALL改寫(xiě)為如下的形式:

select empno,ename from emp where empno=7782

union all

select empno,ename from emp where empno=7698

union all

select empno,ename from emp where empno=7654

8. CONNECT BY

CONNECT BY是Oracle數(shù)據(jù)庫(kù)中層次查詢(Hierachical Queries)所對(duì)應(yīng)的關(guān)鍵字,如果出現(xiàn)在執(zhí)行中也是表示同樣的含義。

看一下實(shí)例:

zx@MYDB>select empno,ename,job,mgr from scott.emp;

     EMPNO ENAME			  JOB				     MGR
---------- ------------------------------ --------------------------- ----------
      7369 SMITH			  CLERK 			    7902
      7499 ALLEN			  SALESMAN			    7698
      7521 WARD 			  SALESMAN			    7698
      7566 JONES			  MANAGER			    7839
      7654 MARTIN			  SALESMAN			    7698
      7698 BLAKE			  MANAGER			    7839
      7782 CLARK			  MANAGER			    7839
      7788 SCOTT			  ANALYST			    7566
      7839 KING 			  PRESIDENT
      7844 TURNER			  SALESMAN			    7698
      7876 ADAMS			  CLERK 			    7788
      7900 JAMES			  CLERK 			    7698
      7902 FORD 			  ANALYST			    7566
      7934 MILLER			  CLERK 			    7782

從上述內(nèi)容可以看到KING是PRESIDENT,它所在記錄的MGR的值為NULL,表示KING沒(méi)有上級(jí)。

我們執(zhí)行如下SQL,從KING所在的記錄開(kāi)始,將所有人按照上下級(jí)關(guān)系分成顯示出來(lái):

zx@MYDB>select empno,ename,mgr from emp start with empno=7839 connect by prior empno=mgr;

     EMPNO ENAME				 MGR
---------- ------------------------------ ----------
      7839 KING
      7566 JONES				7839
      7788 SCOTT				7566
      7876 ADAMS				7788
      7902 FORD 				7566
      7369 SMITH				7902
      7698 BLAKE				7839
      7499 ALLEN				7698
      7521 WARD 				7698
      7654 MARTIN				7698
      7844 TURNER				7698
      7900 JAMES				7698
      7782 CLARK				7839
      7934 MILLER				7782

查看執(zhí)行計(jì)劃:

Oracle里另外一些典型的執(zhí)行計(jì)劃

從上述顯示內(nèi)容可以看出,現(xiàn)在該SQL的執(zhí)行計(jì)劃走的就是CONNECT BY,在執(zhí)行計(jì)劃中我們也能看到CONNECT BY 關(guān)鍵字。


向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI