SQLSERVR语句 in和exists哪个效率高本人测试证明

最近很多人讨论in和exists哪个效率高,今天就自己测试一下

我使用的是客户的数据库GPOSDB(已经有数据)

环境:SQLSERVER2005   Windows7

我的测试条件:两个表作连接根据VC_IC_CardNO字段,查出CT_InhouseCard表中的VC_IC_CardNO(卡号)在CT_FuelingData表中存在的记录

前提:某些人可能在SQL语句中有多个in,或者多个exists,这些情况很难测试效率的,因为大家的条件都不相同

例如下面两个SQL语句

 SELECT  OrderNo, SiteCode, AreaCode
FROM SchedulingProgram
WHERE AreaCode IN ( 'P', 'M' ) AND SiteCode IN ( SELECT SiteCode
FROM EnvBasicInfo
WHERE cityiD = 31 ) AND OrderNo NOT IN (
SELECT OrderNo
FROM KK_DeliveryinfoTmp )

上面SQL语句IN里面有IN和NOT IN

 SELECT  OrderNo, SiteCode, AreaCode
FROM SchedulingProgram
WHERE ( AreaCode IN ( 'P', 'M' ) AND SiteCode IN ( SELECT SiteCode
FROM EnvBasicInfo
WHERE cityiD = 31 )
) AND NOT EXISTS ( SELECT OrderNo
FROM KK_DeliveryinfoTmp
WHERE KK_DeliveryinfoTmp.OrderNo = SchedulingProgram.OrderNo )

上面的SQL语句IN里面又有NOT EXISTS

这样的情况很难测试同等条件下IN语句和EXISTS语句的效率

还有一个非SARG运算符

在《SQLSERVER企业级平台管理实践》的第424页里提到:

SQLSERVER对筛选条件(search argument/SARG)的写法有一定的建议

对于不使用SARG运算符的表达式,索引是没有用的,SQLSERVER对它们很难使用比较优化的做法。非SARG运算符包括

NOT、<>、NOT EXISTS、NOT IN、NOT LIKE和内部函数,例如:Convert、Upper等

所以当您的表中有索引并且SQL语句包含非SARG运算符,那么当测试SQL语句的执行时间的时候肯定相差很大,

因为有些SQL语句走索引,有些SQL语句不走索引


建表脚本

注意:两个表中都有索引!!

CT_FuelingData表

 USE [GPOSDB]
GO
/****** 对象: Table [dbo].[CT_FuelingData] 脚本日期: 08/24/2013 11:00:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[CT_FuelingData](
[RecordNO] [int] IDENTITY(1,1) NOT NULL,
[I_FD_StationNo] [int] NOT NULL,
[VC_FD_No] [varchar](50) NOT NULL,
[VC_FD_Cardno] [varchar](50) NOT NULL,
[I_FD_CardStatus] [int] NULL,
[LI_FD_CTC] [bigint] NOT NULL,
[I_FD_TypeCode] [int] NULL,
[I_FD_PumpID] [int] NOT NULL,
[VC_FD_OilType] [varchar](50) NULL,
[DE_FD_Volume] [decimal](18, 2) NULL,
[DE_FD_Price] [decimal](18, 2) NULL,
[DE_FD_Amount] [decimal](18, 2) NULL,
[I_FD_Point] [decimal](10, 2) NULL,
[D_FD_DateTime] [datetime] NOT NULL,
[VC_FD_GroupNo] [varchar](50) NULL,
[D_FD_GroupDate] [datetime] NULL,
[DE_FD_CardAmount] [decimal](18, 2) NULL,
[DE_FD_VolumeTotals] [decimal](18, 2) NULL,
[DE_FD_AmountTotals] [decimal](18, 2) NULL,
[I_FD_ISSend] [int] NULL,
[VC_FD_CardMoneyauthFile] [varchar](50) NULL,
[D_Month] [datetime] NULL,
CONSTRAINT [PK_CT_FuelingData_1] PRIMARY KEY CLUSTERED
(
[VC_FD_No] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] GO
SET ANSI_PADDING OFF

CT_InhouseCard表

 USE [GPOSDB]
GO
/****** 对象: Table [dbo].[CT_InhouseCard] 脚本日期: 08/24/2013 10:59:58 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[CT_InhouseCard](
[RecordNO] [int] IDENTITY(1,1) NOT NULL,
[VC_IC_CardNO] [varchar](50) NOT NULL,
[VC_IC_PhysicalNO] [varchar](50) NULL,
[I_IC_CardType] [int] NULL,
[VC_IC_UserName] [varchar](50) NULL,
[VC_IC_JobNO] [varchar](50) NULL,
[VC_IC_UserID] [varchar](50) NULL,
[VC_IC_Password] [varchar](50) NULL,
[DE_IC_CardAmount] [decimal](18, 2) NULL,
[DE_IC_AppendAmount] [decimal](18, 2) NULL,
[DE_IC_ConsumerAmount] [decimal](18, 2) NULL,
[I_IC_ISLost] [int] NULL,
[D_IC_UsedDateTime] [datetime] NULL,
[D_IC_UselifeDateTime] [datetime] NULL,
[I_IC_IssueStationNO] [int] NULL,
[VC_IC_IssuerNO] [varchar](50) NULL,
[D_IC_IssueDateTime] [datetime] NULL,
[D_IC_LastUpdateDateTime] [datetime] NULL,
[I_IC_CardStatus] [int] NULL,
[VC_IC_Remark] [varchar](256) NULL,
CONSTRAINT [PK_CT_InhouseCard] PRIMARY KEY CLUSTERED
(
[VC_IC_CardNO] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] GO
SET ANSI_PADDING OFF

测试脚本

因为这个是客户的数据库,本来里面已经有数据了,所以在测试之前先更新两个表的统计信息,以做到公正

 USE [GPOSDB]
GO
UPDATE STATISTICS CT_FuelingData
UPDATE STATISTICS CT_InhouseCard
GO

IN语句

 USE [GPOSDB]
GO
DBCC DROPCLEANBUFFERS
GO
DBCC FREEPROCCACHE
GO
SET STATISTICS IO ON
GO
SET STATISTICS TIME ON
GO
SET STATISTICS PROFILE ON
GO
SELECT * FROM [dbo].[CT_FuelingData] WHERE [VC_FD_Cardno] IN (SELECT [VC_IC_CardNO] FROM [dbo].[CT_InhouseCard])

EXISTS语句

 USE [GPOSDB]
GO
DBCC DROPCLEANBUFFERS
GO
DBCC FREEPROCCACHE
GO
SET STATISTICS IO ON
GO
SET STATISTICS TIME ON
GO
SET STATISTICS PROFILE ON
GO
SELECT *
FROM [dbo].[CT_FuelingData]
WHERE EXISTS ( SELECT [VC_IC_CardNO]
FROM [dbo].[CT_InhouseCard]
WHERE [dbo].[CT_FuelingData].[VC_FD_Cardno] = [dbo].[CT_InhouseCard].[VC_IC_CardNO] )

测试结果

IN语句

 SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 2 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。 SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。 SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。 SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 31 毫秒,占用时间 = 67 毫秒。 (167 行受影响)
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'CT_FuelingData'。扫描计数 1,逻辑读取 31 次,物理读取 1 次,预读 64 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'CT_InhouseCard'。扫描计数 1,逻辑读取 2 次,物理读取 1 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 (4 行受影响) SQL Server 执行时间:
CPU 时间 = 16 毫秒,占用时间 = 192 毫秒。

EXISTS语句

 SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。 SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 34 毫秒。 (167 行受影响)
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'CT_FuelingData'。扫描计数 1,逻辑读取 31 次,物理读取 1 次,预读 64 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'CT_InhouseCard'。扫描计数 1,逻辑读取 2 次,物理读取 1 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。 (4 行受影响) SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 163 毫秒。

大家可以看到除了执行时间有一点差别,IO是一样的

因为数据量比较大,所以两个查询都用到了Worktable(中间表)来存储中间结果

IN语句的执行计划

EXISTS语句的执行计划

从执行计划可以看到两个SQL语句的开销都是一样的,而且大家都使用了右半连接(Right Semi Join)

至于什么是半连接(Semi-join)大家可以看一下这篇文章:SQL Join的一些总结

总结

从上面实际的执行来比较,,IN语句和EXISTS语句基本上都是一样的效率

如有不对的地方,欢迎大家来拍砖o(∩_∩)o

SQLSERVER语句 in和exists哪个效率高本人测试证明的更多相关文章

  1. in和exists哪个效率高本人测试证明

    in和exists哪个效率高本人测试证明 SQLSERVR语句 in和exists哪个效率高自己测试本人测试证明 最近很多人讨论in和exists哪个效率高,今天就自己测试一下 我使用的是客户的数据库 ...

  2. 为什么switch...case语句比if...else执行效率高

    在C语言中,教科书告诉我们switch...case...语句比if...else if...else执行效率要高,但这到底是为什么呢?本文尝试从汇编的角度予以分析并揭晓其中的奥秘. 第一步,写一个d ...

  3. 为什么说在使用多条件判断时switch case语句比if语句效率高?

    在学习JavaScript中的if控制语句和switch控制语句的时候,提到了使用多条件判断时switch case语句比if语句效率高,但是身为小白的我并没有在代码中看出有什么不同.去度娘找了半个小 ...

  4. 答:SQLServer DBA 三十问之一: char、varchar、nvarchar之间的区别(包括用途和空间占用);xml类型查找某个节点的数据有哪些方法,哪个效率高;使用存储 过程和使用T-SQL查询数据有啥不一样;

    http://www.cnblogs.com/fygh/archive/2011/10/18/2216166.html 1. char.varchar.nvarchar之间的区别(包括用途和空间占用) ...

  5. 为什么存储过程比sql语句效率高?

    存储过程经过预编译处理 而SQL查询没有 SQL语句需要先被数据库引擎处理成低级的指令 然后才执行 -------------------------------------------------- ...

  6. 关于in与exists的效率讨论

    关于in与exists的效率讨论1).select * from A where id in (select id from B)以上查询使用了in语句,in只执行一次,他查出B表的所有id字段并缓存 ...

  7. SQL点滴35—SQL语句中的exists

    原文:SQL点滴35-SQL语句中的exists 比如在Northwind数据库中有一个查询为 SELECT c.CustomerId,CompanyName FROM Customers c WHE ...

  8. mysql查询语句in和exists二者的区别和性能影响

    mysql中的in语句是把外表和内表作hash 连接,而exists语句是对外表作loop循环,每次loop循环再对内表进行查询.一直大家都认为exists比in语句的效率要高,这种说法其实是不准确的 ...

  9. MySQL IN和EXISTS的效率问题,以及执行优化

    网上可以查到很多这样的说法: 如果查询的两个表大小相当,那么用in和exists差别不大.如果两个表中一个较小,一个是大表,则子查询表大的用exists,子查询表小的用in: 例如:表A(小表),表B ...

随机推荐

  1. mac个人设置

    修改spotlight快捷键 mac默认的command+space和我windows下的习惯冲突,修改为ctrl+space 删除输入法切换的快捷键 因为我不需要切换不同语言的快捷键.中英文切换直接 ...

  2. (转载)Win8.1的版本

    Win8.1版本到底有哪些? Windows 8.1的各版本有什么不同.差别和区别? Win8.1旗舰版有木有? Win8.1最好的版本是哪个? 我应该用哪个版本的Windows 8.1? 之前软媒曾 ...

  3. 模板类 error LNK2019: 无法解析的外部符号

    如果将类模板的声明和实现写在两个独立的文件中,在构建时会出现"error LNK2019: 无法解析的外部符号 "的错误. 解决方法有: 第一种方法,就是把类模板中成员函数的声明和 ...

  4. android基础知识进阶

    1.android Activity的生命周期 http://blog.csdn.net/hpoi/article/details/4629065 2.android Service的生命周期 htt ...

  5. java web系统中时间比sql server中的日期少2天的解决办法

    系统环境 jdk:1.7 数据库:sql server 2008 问题描述 升级1.7之后查询出来的日期就比数据库中的少2天,降回1.6版本的jdk就正常了. 问题原因及解决办法 国内网站有很多不靠谱 ...

  6. ceshi

    % void CLASS cam_xyz_coeff (float rgb_cam[3][4], double cam_xyz[4][3]) % { % double cam_rgb[4][3], i ...

  7. 获取 windows 商店内的 aapx 安装包 并 安装(旁加载)

    这是一篇教程,写在 win10 版<量子破碎>发售近期. 主要原因:windows 商城的应用下载实在难以忍受...... #######2016-4-9更新####### 4-6号通过旁 ...

  8. 【iOS atomic、nonatomic、assign、copy、retain、weak、strong】的定义和区别详解

    一.atomic与nonatomic 1.相同点 都是为对象添加get和set方法 2.不同点 atomic为get方法加了一把安全锁(及原子锁),使得方法get线程安全,执行效率慢 nonatomi ...

  9. 布局包含Image和Title的UIButton

    UIButton中的titleEdgeInsets和imageEdgeInsets可以管理button中image和title的布局. 如果对其理解不够深入,用纯数字进行布局管理,经过不断的调试,还是 ...

  10. win 文字转化为语音

    mshta vbscript:createobject("sapi.spvoice").speak("hello")(window.close)