關於EXISTS的使用及效率

2021-05-01 12:56:57 字數 3355 閱讀 1351

本文參考了不過的oracle部落格http://www.cnblogs.com/yf520gn/archive/2009/01/12/1374359.html 後根據自己的理解來寫的。

建立兩張表t1、t2,其中t1的locline列中的某些值存在於t2的location中

create table t1

(assetnum varchar2(50) not null,

locline  varchar2(50)

)create table t2

(location    varchar2(36),

managedept  varchar2(50),

grade       varchar2(50),

description varchar2(50)

)1. 理解exists的及執行流程

exists subquery

引數subquery 是乙個受限的 select 語句 (不允許有 compute 子句和 into 關鍵字)。

結果型別

boolean

結果值如果子查詢包含行,則返回 true。

select t1.*

from t1

where exists

(select null from t2  where t1.locline = t2.location )

可以這樣理解上面的sql語句

可以理解為:

for x in ( select * from t1 )

loop

if ( exists (select null from t2 where t2.location = x.locline)

then

output the record

end if

end loop

我的理解是這樣的:首先從t1中取出乙個locline的值,假設這個值為xx, 然後執行select null from t2  where t2.location = xx,如果t2.location存在乙個xx的值,那麼此時就會得到一條記錄,此時的where exists(select null from t2  where t1.locline = t2.location )就為true;那麼最後就會查詢出 t1中locline的值為xx的那些記錄,即最終執行了這樣一條sql語句 select t1.* from t1 where t1.locline = xx;然後繼續從t1中取出下乙個locline的值......

對於exists後的select null 這是無關緊要的,(select t2.* from t2  where t1.locline = t2.location )或者 (select t2.location from t2  where t1.locline = t2.location )或者(select 1 from t2  where t1.locline = t2.location )等等都是可以的,我們只是要得出某條記錄在t2表是否存在,並不需要查詢t2表中的任何列的資料,所以使用select null,但是是否在效能上有所影響,還沒有研究過。

2.exists和in的效能區別

exist 會利用索引來檢索,而in不用

select t1.*

from t1

where exist

(select null from t2  where t1.locline = t2.location )

select t1.*

from t1

where t1.locline in

(select t2.location from t2 )

表 t1 不可避免的要被完全掃瞄一遍,如果t1表的較小,而t2較大時則用exists效率會比較高,並且如果表t2上有索引時,查詢時會用到t2上的索引。如果是t1表較大,而t2表較小時,則採用in。

其實我們區分in和exists主要是造成了驅動順序的改變(這是效能變化的關鍵),如果是exists,那麼以外層表為驅動表,先被訪問,如果是in,那麼先執行子查詢,所以我們會以驅動表的快速返回為目標,那麼就會考慮到索引及結果集的關係了

3.not exists和not in的比較

sql1:

select count(*)

from t1

where not exists

(select null from t2  where t1.locline = t2.location )

sql2:

select count(*)

from t1

where t1.locline not in

(select t2.location from t2 )

not exists 與 not in 不能完全互相替換,看具體的需求。如果選擇的列可以為空,則不能被替換。

我測試的t1表中有952條記錄的locline的值為null,其他的值在t2表中都存在;

sql1執行的結果是:952, 而sql2的執行結果是0

之所以是這樣的結果,對於sql1,在t1中取出了一條locline為null的記錄,很顯然執行子查詢not exists (select null from t2  where t1.locline = t2.location )時返回結果為true;而對於sql2,先執行子查詢select t2.location from t2,然後在t1中取出了一條locline為null的記錄,顯然locline為null的值在t2表中不存在。在這種情況下要使得

sql1和sql2執行結果一樣,可以這樣修改sql2

select count(t1.assetnum)

from t1

where  t1.locline not in

(select t2.location from t2 )

union

select count(t1.assetnum)

from t1

where t1.locline is null

如果需要排除locline為空的記錄,則可以這樣修改sql1

select count(*)

from t1

where not exists

(select null from t2  where t1.locline = t2.location ) and t1.locline is not

null

對於not in 和 not exists的效能區別:

not in 只有當子查詢中,select 關鍵字後的字段有not null約束或者有這種暗示時用not in,另外如果主查詢中表大,子查詢中的錶小但是記錄多,則應當使用not in

如果主查詢表中記錄少,子查詢表中記錄多,並有索引,可以使用not exists.

以上是我個人對exist使用的理解。

SQL中EXISTS與IN的使用及效率

in 和exists 對於以上兩種查詢條件,in是把外表和內錶作hash 連線,而exists 是對外表作loop 迴圈,每次loop 迴圈再對內表進行查詢。一直以來認為exists 比in 效率高的說法是不準確的。在不同的情況下,exists與in的效能各有優缺項,如果查詢的兩個表大小相當,那麼用...

關於exists 的使用

近來幹活時發現對同事寫的用exists的sql看不很懂,在網上蒐集了些資料學習學習。下面這些說法不見的都對,有不對的地方請高手指正。1 exists 字面意思存在。exists裡的子查詢結果集非空,exists 子句的值就是true。exists裡的子查詢結果集為空,exists 子句的值就是fal...

exists和in的查詢及效率比較

有兩個簡單例子,以說明 exists 和 in 的效率問題 sql 1 select from t1 where exists select 1 from t2 where t1.a t2.a t1資料量小而t2資料量非常大時,t1 2 select from t1 where t1.a in se...