优化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执行时间要短很多了
但是用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操作:
此操作执行时间:
此操作执行时间:
此操作执行时间:
使用join连接替代方案:
此操作执行时间:
此操作执行时间:
此操作执行时间:
可以看出使用join方案比使用notin和in执行时间要短很多了
相关文章推荐
- SQLServer 优化SQL语句 in 和not in的替代方案
- SQLServer 优化SQL语句:in 和not in的替代方案
- 优化SQL语句:in 和not in的替代方案
- SQLServer 优化SQL语句:in 和not in的替代方案
- 优化SQL语句:in 和not in的替代方案
- SQLServer 优化SQL语句:in 和not in的替代方案
- 优化SQL语句:in 和not in的替代方案
- SQLServer 优化SQL语句 in 和not in的替代方案
- SQLServer 优化SQL语句 in 和not in的替代方案
- SQLServer 优化SQL语句 in 和not in的替代方案
- SQLServer 优化SQL语句 in 和not in的替代方案
- sql语句优化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的语句
- Sql语句优化之用exists、not exists替代in、not in
- sql语句优化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的语句
- sql语句优化--用EXISTS替代IN、用NOT EXISTS替代NOT IN
- sql语句优化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的语句
- SQL语句Not IN优化方案
- SQL语句优化—in,not in,exists,not exists, left join...on
- SQL(九)-IN,NOT IN语句
- SQL语句优化方案