关于T-SQL中exists或者not exists子查询的“伪优化”的做法
问题起源
在使用t-sql中的exists(或者not exists)子查询的时候,不知道什么时候开始,发现一小部分人存在一种“伪优化”的一些做法,
并且向不明真相的群众传递这一种写法“优越性”,实在看不下去,
无法传递给他人正确的指导思想无可厚非,给他人传递错误的思想或者说误导人倒是一种罪恶。
本来这个事情是不值得一提的,看到越来越多被误导的群众开始推崇这种做法(甚至开始坚信了),实在是看不习惯,不吐不快。
典型的问题如下
select * from TableA a
where exists
(select 1 from TableB b where a.Id = b.Id ),当然这里子查询里写成select * 也无所谓。
这个要表达的逻辑就是说B表中存在与A表相同的Id的数据,就成立,这是要表达的逻辑。
参考如下写法,有人偏偏在在exists子查询中加上top 1 1,问其原因,为什么提高性能?理由就是加了top 1 1,只要在TableB中存在一条满足条件的条件即可,同时不用返回所有的行和列,因此可以提高性能。
select * from TableA a
where exists
(select top 1 1 from TableB b where a.Id = b.Id )
与直接写select 1 from TableB where a.Id =b.Id相比,真的可以提高性能吗?
exists(或者not exists)子查询的实现是一种半连接的“探测”逻辑机制(Semi Join),意思就是只要存在(而不关心具体有多少条)符合条件的数据即可,当然是不会再B表中找到所有的数据行(或者列)之后再返回。
但是exists(或者not exists)具体在执行的时候,到底走不走Semi Join不一定,跟具体的执行计划有关,本文暂不讨论走不走Semi Join的问题,只讨论子查询中select top 1 1 的写法到底影不影响效率。
测试验证
就以AdventureWorks2012示例库的两个表做demo,看看两者的执行计划和IO信息,会发现子查询中加不加 top 1,执行计划一样,IO一样,扯什么性能……


exists(或者not exists)的半连接的逻辑机制(Semi Join)决定了,你写不写top 1,它都是找到一个符合条件的数据之后就返回外层查询,
甚至在子查询中写select * from TableName,如果走Semi Join的执行方式,他照样是探测到有一条存在的数据之后就返回,肯定不会把所有的行都给找出来再返回,
以下截图可以看到,即便子查询是select * ,IO信息也是一样的(当然执行计划也一样)。
在当前这种情况下,可以认为exists子查询中的*,也是不会影响效率什么的。

甚至是可以在子查询中select一个常量,也不会影响到效率或者说改变执行计划。

总结
这个问题比较简答,当然这个场景也仅限于sqlserver中的exists或者not exists子查询,对于别的数据库也不确定是不是优化器内部会自动优化。
当前这种场景下,对于sqlserver来说,不要费尽心思去刻意用select top 1 1去“优化”了。
关于T-SQL中exists或者not exists子查询的“伪优化”的做法的更多相关文章
- SQL中IN,NOT IN,EXISTS,NOT EXISTS的用法和差别
SQL中IN,NOT IN,EXISTS,NOT EXISTS的用法和差别: IN:确定给定的值是否与子查询或列表中的值相匹配. IN 关键字使您得以选择与列表中的任意一个值匹配的行. 当要获得居住在 ...
- 在论坛中出现的比较难的sql问题:4(row_number函数+子查询 分组连续编号问题)
原文:在论坛中出现的比较难的sql问题:4(row_number函数+子查询 分组连续编号问题) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路. 求一查询语句 http: ...
- 在论坛中出现的比较难的sql问题:32(row_number函数+子查询 sql循环取差值)
原文:在论坛中出现的比较难的sql问题:32(row_number函数+子查询 sql循环取差值) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路. sql循环取差值,该怎 ...
- 在论坛中出现的比较难的sql问题:31(row_number函数+子查询 月环比计算)
原文:在论坛中出现的比较难的sql问题:31(row_number函数+子查询 月环比计算) 所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路.
- 在论坛中出现的比较难的sql问题:2(row_number函数+子查询)
原文:在论坛中出现的比较难的sql问题:2(row_number函数+子查询) 2.如何去掉字段内的重复.
- 数据库常用SQL语句(三):子查询
一.为什么会使用子查询 虽然可以通过连接查询来实现多表查询数据记录,但不建议使用,因为连接查询的性能很差,为什么呢?我们来进行分析,例如 我们要查询部门表t_dept 和雇员表t_employee中的 ...
- 为什么sql里面not in后面的子查询如果有记录为NULL的,主查询就查不到记录
为什么sql里面not in后面的子查询如果有记录为NULL的,主查询就查不到记录???原因很简单: SELECT * FROM dbo.TableA AS a WHERE a.id NOT IN ( ...
- sql中 in , not in , exists , not exists效率分析
in和exists执行时,in是先执行子查询中的查询,然后再执行主查询.而exists查询它是先执行主查询,即外层表的查询,然后再执行子查询. exists 和 in 在执行时效率单从执行时间来说差不 ...
- SQL Server进阶(五)子查询
概述 子查询的概念: 当一个查询是另一个查询的条件时,称之为子查询.子查询可以嵌套在主查询中所有位置,包括SELECT.FROM.WHERE.GROUP BY.HAVING.ORDER BY. 外面的 ...
随机推荐
- C#根据进程名称获取进程的句柄?
C#根据进程名称获取进程的句柄或C#如何获取其他进程的句柄? 有时候标题名是动态变化的,所以不使用FindWindow方法! [StructLayout(LayoutKind.Sequential)] ...
- 一篇文章,教你学会Git
在日常工作中,经常会用到Git操作.但是对于新人来讲,刚上来对Git很陌生,操作起来也很懵逼.本篇文章主要针对刚开始接触Git的新人,理解Git的基本原理,掌握常用的一些命令. 一.Git工作流程 以 ...
- KVM总结-KVM性能优化之CPU优化
前言 任何平台根据场景的不同,都有相应的优化.不一样的硬件环境.网络环境,同样的一个平台,它跑出的效果也肯定不一样.就好比一辆法拉利,在高速公路里跑跟乡村街道跑,速度和激情肯定不同… 所以,我们做运维 ...
- css的优化规则
1.避免过度约束: // 不推荐 ul.nav{..} // 推荐 .nav{..} 2.避免过长的后代选择符: // 不推荐 html div tr td {..} 3.避免链式(交集)选择符: ...
- Codeforces Round #492 (Div. 2)
A. /* 从大往小依次除 */ #include<cstdio> #include<algorithm> #include<cstring> #include&l ...
- 【Selenium-WebDriver自学】Log4J的设置(十五)
==================================================================================================== ...
- 数据库设计和ER模型-------之数据库系统生存期(第二章)
数据库设计 概念:开发人员利用开发环境表达用户要求.设计构造最优的数据模型,然后据此建立数据库以及其应用系统,这个过程称为数据库设计 数据库生存期 1968年首次提出“软件工程”的概念 概念:我们把数 ...
- 【HQL】常用函数
CONCAT_WS(separator, str1, str2,...) 多列转1列,以分割符分割 使用场景: 1.多列在一列显示: 2.多列转多行作为辅助,结合split和explode使用 SEL ...
- 21.xpath定位中id 、starts-with、contains、text()和last() 的用法
xpath语法:id .starts-with.contains.text()和last() 的用法 <input id="su" class="bg s_btn ...
- 7.纯 CSS 创作一个 3D 文字跑马灯特效
原文地址:https://segmentfault.com/a/1190000014663038 感想:简单的从右到左动画 HTML代码: <div class="box"& ...