SQL Server里的INTERSECT
在今天的文章里,我想讨论下SQL Server里的INTERSECT设置操作。INTERSECT设置操作彼此交叉2个记录集,返回2个集里列值一样的记录。下图演示了这个概念。

INTERSECT与INNER JOIN
你会发现,它和2个表间的INNER JOIN几乎一样。但今天我会介绍它们之间的一些重要区别。让我们从创建作为输入的2个简单表开始。
-- Create the 1st table
CREATE TABLE t1
(
Col1 INT,
Col2 INT,
Col3 INT
)
GO -- Create the 2nd table
CREATE TABLE t2
(
Col1 INT,
Col2 INT
)
GO -- Create a unique Clustered Index on both tables
CREATE UNIQUE CLUSTERED INDEX idx_ci ON t1(col1)
CREATE UNIQUE CLUSTERED INDEX idx_ci ON t2(col1)
GO -- Insert some records into both tables
INSERT INTO t1 VALUES (1, 1, 1), (2, 2, 2), (NULL, 3, 3)
INSERT INTO t2 VALUES (2, 2), (NULL, 3)
GO
GO
从T-SQL代码里你可以看到,我也在2个表上创建了唯一聚集索引,并插入了一些测试记录。现在让我们来彼此交叉这2个表:
SELECT Col1, Col2 FROM t1
INTERSECT
SELECT Col1, Col2 FROM t2
GO

SQL Server返回2条记录:列值为2和列值为NULL的记录。这是和INNER JOIN的第1个大区别:如果NULL值出现在2个表里,这些记录会被忽略。当你在Col列上进行2个表之间的INNER JOIN操作,含NULL值的记录不会返回:
SELECT t1.col1, t1.col2 FROM t1
INNER JOIN t2 ON t2.col1 = t1.col1
GO
下图显示了INTERSECT和INNER JOIN方法结果集的不同:

现在我们来分析下INTERSECT设置操作的执行计划。因为在Col列上你有支持的索引,查询优化器可以翻译INTERSECT操作为传统的INNER JOIN逻辑操作。

但这里Nested Loop(Inner Join)并不真正进行INNER JOIN操作。我们来看下为什么。当你查看Nested Loop运算符属性时,你会看到在Clustered Index Seek (Clustered)运算符上有剩余谓语(residual predicate)。

剩余谓语在Col2上评估,因为那列不是刚才创建的聚集索引导航结构的一部分。如我刚开始说的,SQL Server需要在2个表所有列找到匹配的行。使用Clustered Index Seek (Clustered)运算符和剩余谓语,SQL Server只检查在t1表里是否有同样列值的匹配记录。而且Nested Loop运算符本身只返回从一个表的列值——这里是t1表。

因此INNER JOIN只是个左半连接(Left Semi Join):SQL Server检查在右表里是否有我们匹配的记录——如果是的话,匹配的记录从左表返回。Clustered Index Seek (Clustered)上的剩余谓语可以通过提供在导航结构里包含所有必须的列来剔除,如下所示:
-- Create a supporting Non-Clustered Index
CREATE NONCLUSTERED index id_nci ON t1(Col1, Col2)
GO
现在当你再次看INTERSECT运算符的执行计划,你会看到SQL Server在刚才创建的索引进行Index Seek (NonClustered)操作,剩余谓语已经不再需要。

现在当我们删除所有支持的索引结构,我们来看执行计划会变成什么样。
-- Drop all supporting indexes
DROP INDEX id_nci ON t1
DROP INDEX idx_ci ON t1
DROP INDEX idx_ci ON t2
GO
当你再次对2个表进行INTERSECT,现在在执行计划里你会看到Nested Loop (Left Semi Join)运算符。SQL Server现在需要在执行计划里进行左半物理连接,通过在内部上进行Table Scan运算符和在Nested Loop里用剩余谓语进行逐行比较。

这个执行计划并不真的高效,因为在内部Table Scan需要反复进行——对来自外表返回的每一行。如果我们想尽可能高效的进行INTERSECT设置操作,支持的索引非常重要。
小结
INTERSECT设置操作并不可怕,但几乎没人很懂它。当你用它时,你要意识到它和INNER JOIN.之间的区别。你也看到,有很好的索引设计对它非常重要,这样的话查询优化器可以生成很好的执行计划。
感谢关注!
参考文章:
https://www.sqlpassion.at/archive/2015/02/09/intersect-sql-server/
SQL Server里的INTERSECT的更多相关文章
- SQL Server里的INTERSECT ALL
在上一篇文章里,我讨论了INTERSECT设置操作的基础,它和INNER JOIN的区别,还有为什么需要好的索引设计支持.今天我想谈下SQL Server里并未实现的INTERSECT ALL操作. ...
- SQL Server里在文件组间如何移动数据?
平常我不知道被问了几次这样的问题:“SQL Server里在文件组间如何移动数据?“你意识到这个问题:你只有一个主文件组的默认配置,后来围观了“SQL Server里的文件和文件组”后,你知道,有多 ...
- SQL Server里的文件和文件组
在今天的文章里,我想谈下SQL Server里非常重要的话题:SQL Server如何处理文件的文件组.当你用CREATE DATABASE命令创建一个简单的数据库时,SQL Server为你创建2个 ...
- 在SQL Server里我们为什么需要意向锁(Intent Locks)?
在1年前,我写了篇在SQL Server里为什么我们需要更新锁.今天我想继续这个讨论,谈下SQL Server里的意向锁,还有为什么需要它们. SQL Server里的锁层级 当我讨论SQL Serv ...
- SQL Server里的闩锁介绍
在今天的文章里我想谈下SQL Server使用的更高级的,轻量级的同步对象:闩锁(Latch).闩锁是SQL Server存储引擎使用轻量级同步对象,用来保护多线程访问内存内结构.文章的第1部分我会介 ...
- 在SQL Server里为什么我们需要更新锁
今天我想讲解一个特别的问题,在我每次讲解SQL Server里的锁和阻塞(Locking & Blocking)都会碰到的问题:在SQL Server里,为什么我们需要更新锁?在我们讲解具体需 ...
- 在SQL Server里如何进行页级别的恢复
在今天的文章里我想谈下每个DBA应该知道的一个重要话题:在SQL Server里如何进行页级别还原操作.假设在SQL Server里你有一个损坏的页,你要从最近的数据库备份只还原有问题的页,而不是还原 ...
- SQL Server里强制参数化的痛苦
几天前,我写了篇SQL Server里简单参数化的痛苦.今天我想继续这个话题,谈下SQL Server里强制参数化(Forced Parameterization). 强制参数化(Forced Par ...
- SQL Server里ORDER BY的歧义性
在今天的文章里,我想谈下SQL Server里非常有争议和复杂的话题:ORDER BY子句的歧义性. 视图与ORDER BY 我们用一个非常简单的SELECT语句开始. -- A very simpl ...
随机推荐
- 用Task代替TheadPool
TheadPool的问题 不支持线程的取消.完成.失败通知等交互性操作 不支持线程执行先后次序 using System; using System.Diagnostics; using System ...
- WebClient的异步处理
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Te ...
- POI 设置EXCEL单元格格式(日期数字文本等)
HSSFCellStyle style0 = workbook2003.createCellStyle(); style0.setBorderBottom(HSSFCellStyle.BORDER_T ...
- Oracle Essbase入门系列(一)
1. 开篇序 本文是几年前做Hyperion Planning项目时写的,后来陆陆续续有些补充.本来打算将整个EPM写一系列的教程,但HFM写到1/3就没动力了.不过至少Essbase这部分是完整的. ...
- Becoming a Data Scientist – Curriculum via Metromap
From: http://nirvacana.com/thoughts/becoming-a-data-scientist/ Data Science, Machine Learning, Big D ...
- “合规性”是考核IT运维的重要指标
ITSM的绩效考核向来是一个令人头疼的问题,有时就像一团乱麻,既无章可循,又无从下手.其实,只要掌握正确的思想方法,就能拨云见日.“斩乱麻”需“快刀”,“合规性考核”就是斩ITSM绩效考核这团乱麻的快 ...
- XSHELL配色方案及导入配色方案的方法
[ubuntu] text(bold)=ffffff magenta(bold)=ad7fa8 text=ffffff white(bold)=eeeeec green=4e9a06 red(bold ...
- 关于DDD的 认识
tks: 第一篇: 领域驱动设计系列(1)通过现实例子显示领域驱动设计的威力 第二篇: 领域驱动设计系列(2)浅析VO.DTO.DO.PO的概念.区别和用处 第三篇: 领域驱动设计系列(3)有选择性的 ...
- [原]quick集成spine动画
更新说明: 新增了骨骼绑定node用法 参考:http://blog.csdn.net/n5/article/details/21795265 在SkeletonRenderer.h 和cpp里面新加 ...
- 像table一样布局div
原文:http://www.456bereastreet.com/archive/200405/equal_height_boxes_with_css/ 下面是我翻译的内容,是根据我对文章的理解意译的 ...