子查詢中的IN與EXISTS的區別(轉)
子查詢中的IN與EXISTS的區別(轉)[@more@] 在複雜的查詢中,選擇正確的子句將會對效能產生很大的影響。考慮一下在你的編碼中使用過哪一些子句。 在主要/明細關係表中寫一個SQL的時候,多數人都會經歷這麼一步,那就是決定是使用WHERE EXISTS(…)子句還是WHERE值IN(…)子句來編寫查詢語句。你可能會拒絕使用WHERE EXISTS,因為用它來編寫的話,要返回一個值,在語法上很困難,而這正是你經常忽視的。 可是,如果你使用基於規則的最最佳化的話,情況就會大不相同了。你可以透過了解哪個表是驅動表,以及每一部份會返回多少行,來確定一個基於規則的查詢的效能。 當你用IN子句來寫一個查詢語句的時候,就等於你向該基於規則的最最佳化傳達了這樣一個資訊,即你想讓內部的查詢推動外部的查詢(假定:IN=由裡而外)。舉例來說,為在一個有14行記錄的EMP表中查詢員工名稱等於“KING”的所有記錄到一個直接報表中,你可以這樣寫: select ename from emp e where mgr in (select empno from emp where ename = 'KING'); 以下是關於這個查詢的說明計劃: OBJECT OPERATION SELECT STATEMENT() NESTED LOOPS() EMP TABLE ACCESS(FULL) EMP TABLE ACCESS(BY INDEX ROWID) PK_EMP INDEX(UNIQUE SCAN) 這個查詢實際上等同於以下這個: select e1.ename from emp e1,(select empno from emp where ename = 'KING') e2 where e1.mgr = e2.empno; 你可以用EXISTS寫同樣的查詢,你只要把外部查詢一欄移到一個像下面這樣的子查詢環境中就可以了: select ename from emp e where exists (select 0 from emp where e.mgr = empno and ename = 'KING'); 當你在一個WHERE子句中寫EXISTS時,又等於向最最佳化傳達了這樣一條資訊,即你想讓外部查詢先執行,使用每一個值來從內部查詢(假定:EXISTS=由外而內)中得到一個值。 關於這個查詢的說明計劃如下: OBJECT OPERATION SELECT STATEMENT() FILTER() EMP TABLE ACCESS(FULL) EMP TABLE ACCESS(BY INDEX ROWID) PK_EMP INDEX(UNIQUE SCAN) 這實際上與PL/SQL編碼類似: set serveroutput on; declare l_count integer; begin for e in (select mgr,ename from emp) loop select count(*) into l_count from emp where e.mgr = empno and ename = 'KING'; if l_count != 0 then dbms_output.put_line(e.ename); end if; end loop; end; 為了確定在基於規則的最最佳化中,哪一種子句效能更佳,不妨考慮一下,與外部查詢相比,內部查詢會返回多少行記錄。許多情況下,EXISTS的表現更突出,這是因為,它需要你指定一個加入條件,這就可以呼叫一個INDEX掃描。儘管如此,如果該查詢的結果很小的話,IN常常表現得更好。你通常都願意執行那些能首先返回較少的結果的查詢。 有些人儘量避免使用EXISTS子句,這是因為,它要求必須從該查詢中返回一個結果,縱使這個結果根本就不會用到。由於個人喜好的原因,人們經常使用‘x’,1,0或零。從說明計劃的輸出我們可以看到,它顯示了,最最佳化會一直使用0而拒絕接受你所有輸入的其它任何值。許多開發人員有這樣一種習慣,那就是經常輸入一些常量。 如果你想執行一下你自己的測試,或者想看看其它的例子,以下是我使用的兩個指令碼: REM -- explain.sql - view plan from PLAN_TABLE set feedback off set verify off set pages 2000 column operation format a40 column object format a10 TTITLE * STATEMENT_ID = '&1' * select object_name object, lpad(' ',level-1)||operation||'('||options||')' operation from plan_table start with id = 0 and statement_id = '&1' connect by prior id = parent_id and statement_id = '&1'; REM -- exists.sql - examples with EXPLAIN PLAN REM -- IN vs. EXISTS REM -- if you don't have a PLAN_TABLE, run ... REM -- @?/rdbms/admin/xplan alter session set optimizer_goal = rule; truncate table plan_table; REM -- find direct reports to KING explain plan set statement_id = 'IN' for select ename from emp e where mgr in (select empno from emp where ename = 'KING'); explain plan set statement_id = 'JOIN-IN' for select e1.ename from emp e1,(select empno from emp where ename = 'KING') e2 where e1.mgr = e2.empno; explain plan set statement_id = 'EXISTS' for select ename from emp e where exists (select 0 from emp where e.mgr = empno and ename = 'KING'); explain plan set statement_id = '=' for select ename from emp e where mgr = (select empno from emp where ename = 'KING'); explain plan set statement_id = 'JOIN1' for select e1.ename from emp e1,emp e2 where e1.mgr = e2.empno and e2.ename = 'KING'; REM -- find employees with greater than average salaries explain plan set statement_id = '>' for select ename from emp e where e.sal > (select avg(sal) from emp); explain plan set statement_id = 'JOIN2' for select e1.ename from emp e1,(select avg(sal) sal from emp) e2 where e1.sal > e2.sal; @@explain IN @@explain JOIN-IN @@explain EXISTS @@explain = @@explain JOIN1 @@explain > @@explain JOIN2
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10763080/viewspace-948382/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- exists與in子查詢優化優化
- [精選] SQL中的IN與NOT IN、EXISTS與NOT EXISTS的區別及效能分析SQL
- 對線面試官:SQL中的IN與NOT IN、EXISTS與NOT EXISTS的區別及效能分析面試SQL
- MySQL exists關聯子查詢SQL效能及其低下最佳化之等值子查詢轉換MySql
- 在資料庫的查詢與更新中,CHARINDEX與instr的區別?資料庫Index
- mysql求交集:UNION ALL合併查詢,inner join內連線查詢,IN/EXISTS子查詢MySql
- elasticsearch之exists查詢Elasticsearch
- SQL語句中exists和in的區別SQL
- SQL查詢的:子查詢和多表查詢SQL
- 區分關聯子查詢和非關聯子查詢
- fs.exists 與 fs.access的區別是什麼
- 15、Oracle中的高階子查詢Oracle
- Linux中的查詢命令:find、locate、whereis、which、type及其區別Linux
- [轉帖]Dockerfile中CMD與ENTRYPOINT命令的區別Docker
- 查詢a表中b表沒有的資料,使用not exists
- 在JavaScript中,DOM物件與jQuery物件的區別與轉換JavaScript物件jQuery
- Javascript中“==”與“===”的區別JavaScript
- Python中 ‘==‘ 與‘is‘的區別Python
- Mysql中的巢狀子查詢問題QSBSMySql巢狀
- 樹狀陣列的區間查詢與區間修改陣列
- 複雜查詢—子查詢
- c#中Array,ArrayList 與List<T>的區別、共性與轉換C#
- 什麼是SQL 語句中相關子查詢與非相關子查詢SQL
- 在 with 查詢中只查詢個別欄位
- Java中(==)與equals的區別Java
- Mysql資料庫使用from與join兩表查詢的方法區別總結MySql資料庫
- 如何在word中進行查詢與替換 word文件中的替換與查詢功能
- Java中HashMap,LinkedHashMap,TreeMap的區別[轉]JavaHashMap
- spring中的FactoryBean與ObjectFactory的區別SpringBeanObject
- MYsql 子查詢MySql
- MySQL子查詢MySql
- 子串查詢
- XHTML?它與 HTML的區別?如何轉換HTML
- Elasticsearch中的Term查詢和全文查詢Elasticsearch
- js中 let 與 var 的區別JS
- vue中sass與SCSS的區別VueCSS
- js中!和!!的區別與用法JS
- JavaScript 中substr與 substring 的區別JavaScript
- Vue 中ref()與 reactive() 的區別VueReact