在使用Exists時,如果能正確使用,有時會提高查詢速度:
1,使用Exists代替inner join
2,使用Exists代替 in
1,使用Exists代替inner join例子:
在一般寫sql語句時通常會遇到如下語句:
兩個表連接時,取一個表的數據,一般的寫法通過關聯查詢(inner join):
from dbo. [ [zping.com ] ]] a
inner join workflowbase b on a.workflowid = b.id
and operator = ' 4028814111ad9dc10111afc134f10041 '
查詢結果:
表 ' Worktable ' 。掃描計數 0 ,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 ' workflowbase ' 。掃描計數 1 ,邏輯讀取 293 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 ' [zping.com] ' 。掃描計數 1 ,邏輯讀取 1339 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
還有一種寫法使用exists來取數據
from dbo. [ [zping.com ] ]] a where exists
( select ' X ' from workflowbase b where a.workflowid = b.id)
and operator = ' 4028814111ad9dc10111afc134f10041 '
執行結果:
表 ' [zping.com] ' 。掃描計數 1 ,邏輯讀取 1339 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 ' workflowbase ' 。掃描計數 1 ,邏輯讀取 291 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
這里兩着的IO次數,EXISTS比inner join少 2個IO, 對比執行計划成本不一樣, 看看兩着的差異:
這時我們發現使用EXISTS要比inner join效率稍微高一下。
2,使用Exists代替 in
要求:編寫workflowbase表中id不在表中dbo.[[zping.com]]]的行:
一般的寫法:
where id not in (
select a.workflowid
from dbo. [ [zping.com ] ]] a )
執行結果:
( 1 行受影響)
表 ' Worktable ' 。掃描計數 0 ,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 ' [zping.com] ' 。掃描計數 5 ,邏輯讀取 56952 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 ' workflowbase ' 。掃描計數 3 ,邏輯讀取 1589 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 ' Worktable ' 。掃描計數 0 ,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
使用Existsl來寫:
where not exists (
select ' X '
from dbo. [ [zping.com ] ]] a where a.workflowid = b.id )
看看執行結果
表 ' Worktable ' 。掃描計數 0 ,邏輯讀取 0 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 ' [zping.com] ' 。掃描計數 3 ,邏輯讀取 18984 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
表 ' workflowbase ' 。掃描計數 3 ,邏輯讀取 1589 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。
兩個io的差距:56952+1589=58541次 (使用IN)
18984+1589=20573次 (使用Exists)
使用exists是in的2.8倍,查詢性能提高很大。
EXISTS 使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結果。
in和inner join在大多數情況下都是返回兩表的交集,但是兩者還是有區別的,如下例子
mysql> select * from a;+------+------+
| id | name |
+------+------+
| 1 | a |
| 2 | b |
| 3 | c |
+------+------+
MySQL> select * from b;
+------+------+
| id | name |
+------+------+
| 1 | d |
| 1 | g |
| 2 | e |
| 4 | f |
+------+------+
mysql> select a.id, a.name from a where a.id in (select b.id from b);
+------+------+
| id | name |
+------+------+
| 1 | a |
| 2 | b |
+------+------+
mysql> select a.id, a.name from a inner join b on (a.id = b.id);
+------+------+
| id | name |
+------+------+
| 1 | a |
| 1 | a |
| 2 | b |
+------+------+
mysql> select * from a inner join b on (a.id = b.id);
+------+------+------+------+
| id | name | id | name |
+------+------+------+------+
| 1 | a | 1 | d |
| 1 | a | 1 | g |
| 2 | b | 2 | e |
+------+------+------+------+
從查詢結果中可以看出,in的結果是不會有重復的,對非主鍵進行join時,join的結果是有重復的。如果說還有另一個區別的話就是join會產生一個兩表合並的臨時表,in不會產生兩表合並的臨時表。