1. 程式人生 > >SQL優化--使用 EXISTS 代替 IN 和 inner join來選擇正確的執行計劃

SQL優化--使用 EXISTS 代替 IN 和 inner join來選擇正確的執行計劃

tool pos inner ner 使用 邏輯讀 rda jpg 分享

在使用Exists時,如果能正確使用,有時會提高查詢速度:

1,使用Exists代替inner join

2,使用Exists代替 in

1,使用Exists代替inner join例子:

在一般寫sql語句時通常會遇到如下語句:

兩個表連接時,取一個表的數據,一般的寫法通過關聯查詢(inner join):

select a.id, a.workflowid,a.operator,a.stepid
from dbo.[[zping.com]]] a
inner join workflowbase b on a.workflowid=b.id
and operator=‘4028814111ad9dc10111afc134f10041‘

查詢結果:

(1327 行受影響)
表 ‘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來取數據

select a.id,a.workflowid,a.operator ,a.stepid
from dbo.[[zping.com]]] a where exists
(select ‘X‘ from workflowbase b where a.workflowid=b.id)
and operator=‘4028814111ad9dc10111afc134f10041‘

執行結果:

(1327 行受影響)
表 ‘[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]]]的行:

一般的寫法:

select * from workflowbase
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來寫:

select * from workflowbase b
where not exists(
select ‘X‘
from dbo.[[zping.com]]] a where a.workflowid=b.id )

看看執行結果

(1 行受影響)
表 ‘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核心模塊將在子查詢的條件一旦滿足後,立刻返回結果。

SQL優化--使用 EXISTS 代替 IN 和 inner join來選擇正確的執行計劃