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

但是用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万条测试数据


代码如下:

create procedure AddData
as
declare @id int
set @id=0
while(@id<100000)
begin
insert into dbo.Info(id,PName,remark,impdate,upstate)
values(@id,convert(varchar,@id)+'0','abc',getdate(),0)
set @id=@id+1
end
exec AddData

使用not in 和in操作:


代码如下:

SET STATISTICS TIME ON
GO
--备份数据
insert into bakInfo(id,PName,remark,impdate,upstate)
select id,PName,remark,impdate,upstate from dbo.Info
where id not in(select id from dbo.bakInfo)
GO
SET STATISTICS TIME OFF

此操作执行时间:


代码如下:

SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 3 毫秒。
SQL Server 执行时间:
CPU 时间 = 453 毫秒,占用时间 = 43045 毫秒。
(100000 行受影响)
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
--更改当前表状态
update Info set upstate=1 where id in(select id from dbo.bakInfo)

  此操作执行时间:


代码如下:

SQL Server 分析和编译时间:
CPU 时间 = 62 毫秒,占用时间 = 79 毫秒。
SQL Server 执行时间:
CPU 时间 = 188 毫秒,占用时间 = 318 毫秒。
(100000 行受影响)
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
--删除当前表数据
delete from Info where upstate=1 and id in(select id from dbo.bakInfo)

  此操作执行时间:


代码如下:

SQL Server 分析和编译时间:
CPU 时间 = 183 毫秒,占用时间 = 183 毫秒。
SQL Server 执行时间:
CPU 时间 = 187 毫秒,占用时间 = 1506 毫秒。
(100000 行受影响)
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

  使用join连接替代方案:


代码如下:

SET STATISTICS TIME ON
GO
--备份数据
insert into bakInfo(id,PName,remark,impdate,upstate)
select id,PName,remark,impdate,upstate from
(SELECT Info.id,Info.PName, Info.remark, Info.impdate,Info.upstate, bakInfo.id AS bakID
FROM Info left JOIN
bakInfo ON Info.id = bakInfo.id ) as t
where t.bakID is null and t.upstate=0
GO
SET STATISTICS TIME OFF;

  此操作执行时间:


代码如下:

SQL Server 分析和编译时间:
CPU 时间 = 247 毫秒,占用时间 = 247 毫秒。
SQL Server 执行时间:
CPU 时间 = 406 毫秒,占用时间 = 475 毫秒。
(100000 行受影响)
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
--更改当前表状态
update Info set upstate=1
FROM Info INNER JOIN
bakInfo ON Info.id = bakInfo.id

  此操作执行时间:


代码如下:

SQL Server 分析和编译时间:
CPU 时间 = 4 毫秒,占用时间 = 4 毫秒。
SQL Server 执行时间:
CPU 时间 = 219 毫秒,占用时间 = 259 毫秒。
(100000 行受影响)
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

--删除当前表数据


代码如下:

delete from Info
FROM Info INNER JOIN
bakInfo ON Info.id = bakInfo.id
where Info.upstate=1

  此操作执行时间:


代码如下:

SQL Server 分析和编译时间:
CPU 时间 = 177 毫秒,占用时间 = 177 毫秒。
SQL Server 执行时间:
CPU 时间 = 219 毫秒,占用时间 = 550 毫秒。
(100000 行受影响)
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。

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

(0)

相关推荐

  • Sql Server 索引使用情况及优化的相关Sql语句分享

    复制代码 代码如下: --Begin Index(索引) 分析优化的相关 Sql -- 返回当前数据库所有碎片率大于25%的索引 -- 运行本语句会扫描很多数据页面 -- 避免在系统负载比较高时运行 -- 避免在系统负载比较高时运行 declare @dbid int select @dbid = db_id() SELECT o.name as tablename,s.* FROM sys.dm_db_index_physical_stats (@dbid, NULL, NULL, NULL,

  • oracle下一条SQL语句的优化过程(比较详细)

    原来的语句是这样的: select sum(sl0000) from xstfxps2 where dhao00 in ( select dhao00 from xstfxps1 where trunc(ywrq00)=trunc(sysdate) and khdm00='500000003913'); 已用时间: 00: 02: 49.04 Execution Plan ---------------------------------------------------------- 0 S

  • SQL Server中的SQL语句优化与效率问题

    很多人不知道SQL语句在SQL SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL SERVER误解.比如: select * from table1 where name='zhangsan' and tID > 10000 和执行: select * from table1 where tID > 10000 and name='zhangsan' 一些人不知道以上两条语句的执行效率是否一样,因为如果简单的从语句先后上看,这两个语句的确是不一样,如果tID是一个聚合索引,那

  • SQL语句优化方法30例(推荐)

    1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化. 例如: SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT'; 2. /*+FIRST_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳响应时间,使资源消耗最小化. 例如: SELECT /*+FIRST_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BS

  • sql语句优化之SQL Server(详细整理)

    MS SQL Server查询优化方法 查询速度慢的原因很多,常见如下几种 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6.查询出的数据量过大(可以采用多次查询,其他的方法降低数据量) 7.锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷) 8.sp_lock,sp_who,活动的用户查看,原因是读写竞争资源. 9.返回了不必要的行和列 10.查询语句不好,

  • SQL SERVER 的SQL语句优化方式小结

    1.SQL SERVER 2005的性能工具中有SQL Server Profiler和数据库引擎优化顾问,极好的东东,必须熟练使用. 2.查询SQL语句时打开"显示估计的执行计划",分析每个步骤的情况 3.初级做法,在CPU占用率高的时候,打开SQL Server Profiler运行,将跑下来的数据存到文件中,然后打开数据库引擎优化顾问调用那个文件进行分析,由SQL SERVER提供索引优化建议.采纳它的INDEX索引优化部分. 4.但上面的做法经常不会跑出你所需要的,在最近的优化

  • 浅谈MySQL中优化sql语句查询常用的30种方法

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描. 3.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id from t where num is null 可以在num上设置默认值0,确保表中num列没有null值,然后这样查询: select id from

  • 如何优化SQL语句的心得浅谈

    (1)选择最有效率的表名顺序(只在基于规则的优化器中有效):Oracle的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.(2)WHERE子句中的连接顺序:Oracle采用自下而上的顺序解析WHERE子句,根据

  • MySQL SQL语句优化的10条建议

    1.将经常要用到的字段(比如经常要用这些字段来排序,或者用来做搜索),则最好将这些字段设为索引.2.字段的种类尽可能用int 或者tinyint类型.另外字段尽可能用NOT NULL.3.当然无可避免某些字段会用到text ,varchar等字符类型,最好将text字段的单独出另外一个表出来(用主键关联好)4.字段的类型,以及长度,是一个很考究开发者优化功力的一个方面.如果表数据有一定的量了,不妨用PROCEDURE ANALYSE()命令来取得字段的优化建议!(在phpmyadmin里可以在查

  • 数据库SQL语句优化总结(收藏)

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉好的话推荐给更多的人,让更多的人看到.纠正以及补充. 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如: select id f

  • 常用SQL语句优化技巧总结【经典】

    本文实例总结了常用SQL语句优化技巧.分享给大家供大家参考,具体如下: 除了建立索引之外,保持良好的SQL语句编写习惯将会降低SQL性能问题发生. ①通过变量的方式来设置参数 好: stringsql = "select * from people p where p.id = ? "; 坏: stringsql = "select * from people p where p.id = "+id; 数据库的SQL文解析和执行计划会保存在缓存中,但是SQL文只要有

  • 如何优化SQL语句(全)

    高性能的SQL语句会在软件运行中起到非常重要的作用,下面小编把最近整理的SQL语句优化资料分享给大家. 第一: 选择最有效率的表名顺序(只在基于规则的seo/' target='_blank'>优化器中有效): ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表.如果有3个以上的表连接查询, 那就需要选择交叉表(intersecti

  • SQL语句性能优化(续)

    上篇介绍了一下自己在项目中遇到的一种使用sql语句的优化方式(性能优化--SQL语句),但是说的不够完整.在对比的过程中,没有将max函数考虑在内,经人提醒之后赶紧做了一个测试,测试过程中又学到了不少的东西. 上次用的是select count(*) 和select * 的执行效率问题,因为我的需求是获取数据的一个总数来自动给出新的id,然后网友给出可以使用max的方式给出新id.其实这也是一种不错的思路(当时我们也用过该函数,只不过因为系统数据本身问题,不适合用该函数),然后我就对max函数的

随机推荐