曲演杂坛--EXISTS语句

通常在我写EXISTS语句时,我会写成IF EXISTS(SELECT TOP(1) 1 FROM XXX),也没细细考究过为什么要这么写,只是隐约认为这样写没有啥问题,那今天就深究下吧!

首先准备测试测试数据

复制代码
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
复制代码

以上语句各种写法,但最终生成的执行计划都一样,因此执行效率也一样:

 

对于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

其生成的执行计划为:

 

================================================

 

posted on   笑东风  阅读(675)  评论(3编辑  收藏  举报

编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
历史上的今天:
2014-06-13 曲演杂坛--重建索引后,还使用混合分区么?(Are mixed pages removed by an index rebuild?)

导航

点击右上角即可分享
微信分享提示