優化SQL 語句 in 和not in 的替代方案

iSQlServer發表於2010-03-02

用IN寫出來的SQL的優點是比較容易寫及清晰易懂,這比較適合現代軟體開發的風格。

但是用IN的SQL效能總是比較低的,從SQL執行的步驟來分析用IN的SQL與不用IN的SQL有以下區別:

SQL試圖將其轉換成多個表的連線,如果轉換不成功則先執行IN裡面的子查詢,再查詢外層的表記錄,如果轉換成功則直接採用多個表的連線方 式查詢。由此可見用IN的SQL至少多了一個轉換的過程。一般的SQL都可以轉換成功,但對於含有分組統計等方面的SQL就不能轉換了。 推薦在業務密集的SQL當中儘量不採用IN操作符

NOT IN 此操作是強列推薦不使用的,因為它不能應用表的索引。推薦用NOT EXISTS 或(外連線+判斷為空)方案代替

  在資料庫中有兩個表,一個是當前表Info(id,PName,remark,impdate,upstate),一個是備份資料表 bakInfo(id,PName,remark,impdate,upstate),將當前表資料備份到備份表去,就涉及到not in 和in 操作了:

  首先,新增10萬條測試資料

 

  使用not in 和in操作:

1SET STATISTICS TIME ON
2GO
3--備份資料
4insert into bakInfo(id,PName,remark,impdate,upstate)
5select id,PName,remark,impdate,upstate from dbo.Info
6where id not in(select id from dbo.bakInfo)
7GO
8SET STATISTICS TIME OFF

  此操作執行時間:

01SQL Server 分析和編譯時間:
02   CPU 時間 = 0 毫秒,佔用時間 = 3 毫秒。
03 
04SQL Server 執行時間:
05   CPU 時間 = 453 毫秒,佔用時間 = 43045 毫秒。
06 
07(100000 行受影響)
08SQL Server 分析和編譯時間:
09   CPU 時間 = 0 毫秒,佔用時間 = 1 毫秒。
10 
11 
12--更改當前表狀態
13update  Info set upstate=1 where id in(select id from dbo.bakInfo)

  此操作執行時間:

01SQL Server 分析和編譯時間:
02   CPU 時間 = 62 毫秒,佔用時間 = 79 毫秒。
03 
04SQL Server 執行時間:
05   CPU 時間 = 188 毫秒,佔用時間 = 318 毫秒。
06 
07(100000 行受影響)
08SQL Server 分析和編譯時間:
09   CPU 時間 = 0 毫秒,佔用時間 = 1 毫秒。
10 
11 
12 
13--刪除當前表資料
14delete from Info where upstate=1 and id in(select id from dbo.bakInfo)

  此操作執行時間:

1SQL Server 分析和編譯時間:
2   CPU 時間 = 183 毫秒,佔用時間 = 183 毫秒。
3 
4SQL Server 執行時間:
5   CPU 時間 = 187 毫秒,佔用時間 = 1506 毫秒。
6 
7(100000 行受影響)
8SQL Server 分析和編譯時間:
9   CPU 時間 = 0 毫秒,佔用時間 = 1 毫秒。

 

  使用join連線替代方案:

01SET STATISTICS TIME ON
02GO
03 
04--備份資料
05insert into bakInfo(id,PName,remark,impdate,upstate)
06select id,PName,remark,impdate,upstate from
07(SELECT     Info.id,Info.PName, Info.remark, Info.impdate,Info.upstate, bakInfo.id AS bakID
08FROM         Info left JOIN
09                      bakInfo ON Info.id = bakInfo.id ) as t
10where t.bakID is null and t.upstate=0
11GO
12SET STATISTICS TIME OFF;


  此操作執行時間:

1SQL Server 分析和編譯時間:
2   CPU 時間 = 247 毫秒,佔用時間 = 247 毫秒。
3 
4SQL Server 執行時間:
5   CPU 時間 = 406 毫秒,佔用時間 = 475 毫秒。
6 
7(100000 行受影響)
8SQL Server 分析和編譯時間:
9   CPU 時間 = 0 毫秒,佔用時間 = 1 毫秒。

 

1--更改當前表狀態
2update Info set upstate=1
3FROM         Info INNER JOIN
4                      bakInfo ON Info.id = bakInfo.id

  此操作執行時間:

1SQL Server 分析和編譯時間:
2   CPU 時間 = 4 毫秒,佔用時間 = 4 毫秒。
3 
4SQL Server 執行時間:
5   CPU 時間 = 219 毫秒,佔用時間 = 259 毫秒。
6 
7(100000 行受影響)
8SQL Server 分析和編譯時間:
9   CPU 時間 = 0 毫秒,佔用時間 = 1 毫秒。
1--刪除當前表資料
2 
3delete from Info
4FROM         Info INNER JOIN
5                      bakInfo ON Info.id = bakInfo.id
6where  Info.upstate=1

  此操作執行時間:

1SQL Server 分析和編譯時間:
2   CPU 時間 = 177 毫秒,佔用時間 = 177 毫秒。
3 
4SQL Server 執行時間:
5   CPU 時間 = 219 毫秒,佔用時間 = 550 毫秒。
6 
7(100000 行受影響)
8SQL Server 分析和編譯時間:
9   CPU 時間 = 0 毫秒,佔用時間 = 1 毫秒。

 

  可以看出使用join方案比使用not in 和in執行時間要短很多了

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/16436858/viewspace-628372/,如需轉載,請註明出處,否則將追究法律責任。

相關文章