曲演杂坛--EXISTS语句
2016-06-13 15:40
337 查看
通常在我写EXISTS语句时,我会写成IF EXISTS(SELECT TOP(1) 1 FROM XXX),也没细细考究过为什么要这么写,只是隐约认为这样写没有啥问题,那今天就深究下吧!
首先准备测试测试数据
其中需要注意下索引IDX_ID, 虽然ID已经是主键索引,但仍创建一个非聚集索引以供后续测试。
通常我们在写EXISTS语句时,一个纠结点是要不要使用TOP,另外一个纠结点是SELECT 语句中的返回列,因此构造测试语句如下:
以上语句各种写法,但最终生成的执行计划都一样,因此执行效率也一样:
![](http://images2015.cnblogs.com/blog/174228/201606/174228-20160613151500354-1383995567.png)
对于IF EXISTS(SELECT C1 FROM [dbo].[TB1001] WHERE ID>10)语句,索引IDX_ID并没有包含C1列的数据,但查询仍使用IDX_ID索引,证明查询并不需要访问C1列的数据
从上面的操作运算符来看,可以得到以下两个结论:
1. 无论是TOP(1)还是TOP(10)或不使用TOP,执行计划中都没有TOP的操作,即使SQL语句中写明TOP(1)也会被忽略,因此TOP并不影响生成执行计划;
2. 无论使用SELECT 1 或者使用SELECT * 又或者使用SELECT C1 等,运算符都没有返回列信息(OUTPUT LIST), 即EXISTS并不关心返回数据的内容,只关心有没有数据,因此SELECT部分的内容也不影响生成执行计划;
--========================================================
PS: Seek Keys[1] 并不代表只返回一行数据,如对于查询:
其生成的执行计划为:
![](http://images2015.cnblogs.com/blog/174228/201606/174228-20160613153111901-487710730.png)
================================================
首先准备测试测试数据
USE [TestDB1] GO CREATE TABLE TB1001 ( ID INT IDENTITY(1,1), C1 VARCHAR(200), CONSTRAINT PK_TB1001_ID PRIMARY KEY(ID) ) GO CREATE INDEX IDX_ID ON TB1001(ID) GO INSERT INTO TB1001(C1) SELECT name FROM sys.columns GO
其中需要注意下索引IDX_ID, 虽然ID已经是主键索引,但仍创建一个非聚集索引以供后续测试。
通常我们在写EXISTS语句时,一个纠结点是要不要使用TOP,另外一个纠结点是SELECT 语句中的返回列,因此构造测试语句如下:
IF EXISTS(SELECT 1 FROM [dbo].[TB1001] WHERE ID>10) BEGIN PRINT 1 END IF EXISTS(SELECT TOP(1) 1 FROM [dbo].[TB1001] WHERE ID>10) BEGIN PRINT 1 END IF EXISTS(SELECT TOP(10) 1 FROM [dbo].[TB1001] WHERE ID>10) BEGIN PRINT 1 END IF EXISTS(SELECT * FROM [dbo].[TB1001] WHERE ID>10) BEGIN PRINT 1 END IF EXISTS(SELECT ID FROM [dbo].[TB1001] WHERE ID>10) BEGIN PRINT 1 END IF EXISTS(SELECT C1 FROM [dbo].[TB1001] WHERE ID>10) BEGIN PRINT 1 END
以上语句各种写法,但最终生成的执行计划都一样,因此执行效率也一样:
![](http://images2015.cnblogs.com/blog/174228/201606/174228-20160613151500354-1383995567.png)
对于IF EXISTS(SELECT C1 FROM [dbo].[TB1001] WHERE ID>10)语句,索引IDX_ID并没有包含C1列的数据,但查询仍使用IDX_ID索引,证明查询并不需要访问C1列的数据
从上面的操作运算符来看,可以得到以下两个结论:
1. 无论是TOP(1)还是TOP(10)或不使用TOP,执行计划中都没有TOP的操作,即使SQL语句中写明TOP(1)也会被忽略,因此TOP并不影响生成执行计划;
2. 无论使用SELECT 1 或者使用SELECT * 又或者使用SELECT C1 等,运算符都没有返回列信息(OUTPUT LIST), 即EXISTS并不关心返回数据的内容,只关心有没有数据,因此SELECT部分的内容也不影响生成执行计划;
--========================================================
PS: Seek Keys[1] 并不代表只返回一行数据,如对于查询:
SELECT TOP(10) * FROM [dbo].[TB1001] WHERE ID>10
其生成的执行计划为:
![](http://images2015.cnblogs.com/blog/174228/201606/174228-20160613153111901-487710730.png)
================================================
![](http://images2015.cnblogs.com/blog/174228/201606/174228-20160613153834526-1562193639.jpg)
相关文章推荐
- Hibernate Search-----关联检索
- 接触到的前端网站(仅个人收藏用)
- Linux命令总结
- Android基于AOP的非侵入式监控之——AspectJ实战
- 通向成熟之路
- mysql复制原理/基于库的多线程复制原理/基于BLGC的多线程复制原理
- iOS开发-Could not find a storyboard named 'Main' in bundle NSBundle
- Scala类型系统——高级类类型(higher-kinded types)
- python win系统获取磁盘及文件夹大小
- 给AspNetPager分页控件添加bootstrap样式
- 前端开发 Grunt 之 Connect
- Grunt 之通配符
- Fragment中的onCreatView()没有立即调用
- redis面试题总结
- Java编程思想21.2.1实例
- instanceof
- xshell如何正确来连接远程Linux服务器?
- 【leetcode】110. Balanced Binary Tree
- Grunt 之 watch 和 livereload
- 小孩钢琴练指