您的位置:首页 > 数据库

优化SQL 语句 in 和not in 的替代方案

2010-03-01 21:30 597 查看
用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。
但是用IN的SQL性能总是比较低的,从SQL执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别:
SQL试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。推荐在业务密集的SQL当中尽量不采用IN操作符
NOTIN此操作是强列推荐不使用的,因为它不能应用表的索引。推荐用NOTEXISTS或(外连接+判断为空)方案代替
  在数据库中有两个表,一个是当前表Info(id,PName,remark,impdate,upstate),一个是备份数据表bakInfo(id,PName,remark,impdate,upstate),将当前表数据备份到备份表去,就涉及到notin和in操作了:
  首先,添加10万条测试数据
代码

1createprocedureAddData
2as
3declare@idint
4set@id=0
5while(@id<100000)
6begin
7insertintodbo.Info(id,PName,remark,impdate,upstate)
8values(@id,convert(varchar,@id)+'0','abc',getdate(),0)
9set@id=@id+1
10end
11
12execAddData


  使用notin和in操作:SETSTATISTICSTIMEON GO --备份数据 insertintobakInfo(id,PName,remark,impdate,upstate) selectid,PName,remark,impdate,upstatefromdbo.Info whereidnotin(selectidfromdbo.bakInfo) GO SETSTATISTICSTIMEOFF
  此操作执行时间:SQLServer分析和编译时间: CPU时间=0毫秒,占用时间=3毫秒。 SQLServer执行时间: CPU时间=453毫秒,占用时间=43045毫秒。 (100000行受影响) SQLServer分析和编译时间: CPU时间=0毫秒,占用时间=1毫秒。 --更改当前表状态 updateInfosetupstate=1whereidin(selectidfromdbo.bakInfo)
  此操作执行时间:SQLServer分析和编译时间: CPU时间=62毫秒,占用时间=79毫秒。 SQLServer执行时间: CPU时间=188毫秒,占用时间=318毫秒。 (100000行受影响) SQLServer分析和编译时间: CPU时间=0毫秒,占用时间=1毫秒。 --删除当前表数据 deletefromInfowhereupstate=1andidin(selectidfromdbo.bakInfo)
  此操作执行时间:SQLServer分析和编译时间: CPU时间=183毫秒,占用时间=183毫秒。 SQLServer执行时间: CPU时间=187毫秒,占用时间=1506毫秒。 (100000行受影响) SQLServer分析和编译时间: CPU时间=0毫秒,占用时间=1毫秒。

  使用join连接替代方案:

SETSTATISTICSTIMEON GO --备份数据 insertintobakInfo(id,PName,remark,impdate,upstate) selectid,PName,remark,impdate,upstatefrom (SELECTInfo.id,Info.PName,Info.remark,Info.impdate,Info.upstate,bakInfo.idASbakID FROMInfoleftJOIN bakInfoONInfo.id=bakInfo.id)ast wheret.bakIDisnullandt.upstate=0 GO SETSTATISTICSTIMEOFF;

  此操作执行时间:SQLServer分析和编译时间: CPU时间=247毫秒,占用时间=247毫秒。 SQLServer执行时间: CPU时间=406毫秒,占用时间=475毫秒。 (100000行受影响) SQLServer分析和编译时间: CPU时间=0毫秒,占用时间=1毫秒。
--更改当前表状态 updateInfosetupstate=1 FROMInfoINNERJOIN bakInfoONInfo.id=bakInfo.id
  此操作执行时间:SQLServer分析和编译时间: CPU时间=4毫秒,占用时间=4毫秒。 SQLServer执行时间: CPU时间=219毫秒,占用时间=259毫秒。 (100000行受影响) SQLServer分析和编译时间: CPU时间=0毫秒,占用时间=1毫秒。
--删除当前表数据 deletefromInfo FROMInfoINNERJOIN bakInfoONInfo.id=bakInfo.id whereInfo.upstate=1
  此操作执行时间:SQLServer分析和编译时间: CPU时间=177毫秒,占用时间=177毫秒。 SQLServer执行时间: CPU时间=219毫秒,占用时间=550毫秒。 (100000行受影响) SQLServer分析和编译时间: CPU时间=0毫秒,占用时间=1毫秒。

  可以看出使用join方案比使用notin和in执行时间要短很多了

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: