前言

本节我们来综合比较NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL的性能,简短的内容,深入的理解,Always to review the basics。

NOT IN、NOT EXISTS、LEFT JOIN...IS NULL性能分析

我们首先创建测试表

USE TSQL2012
GO CREATE SCHEMA [compare]
CREATE TABLE [compare].t_left (
id INT NOT NULL PRIMARY KEY,
value INT NOT NULL,
stuffing VARCHAR() NOT NULL
)
CREATE TABLE [compare].t_right (
id INT NOT NULL PRIMARY KEY,
value INT NOT NULL,
stuffing VARCHAR() NOT NULL
)
GO

接着我们在两个表中的列value上创建索引

USE TSQL2012
GO CREATE INDEX idx_left_value ON [compare].t_left (value)
CREATE INDEX idx_right_value ON [compare].t_right (value)

我们在t_left和t_right表中插入如下测试数据

USE TSQL2012
GO BEGIN TRANSACTION
DECLARE @cnt INT
SET @cnt =
WHILE @cnt <=
BEGIN
INSERT
INTO [compare].t_left
VALUES (
@cnt,
@cnt % ,
LEFT('Left ' + CAST(@cnt AS VARCHAR) + ' ' + REPLICATE('*', ), )
)
SET @cnt = @cnt +
END;
WITH rows AS
(
SELECT AS row
UNION ALL
SELECT row +
FROM rows
WHERE row <
)
INSERT
INTO [compare].t_right
SELECT (id - ) * + row + ,
value + ,
LEFT('Right ' + CAST(id AS VARCHAR) + ' ' + REPLICATE('*', ), )
FROM [compare].t_left
CROSS JOIN
rows
COMMIT

我们稍微解释下上述插入的测试数据:

(1)t_left表中插入10万条数据,其中包含1万条重复数据。

(2)t_right表中插入100万条数据,其中包含1万条重复数据。

(3)t_left表中插入10条t_right表中没有的数据。

接下来我们一个个来看看其查询执行计划。

NOT IN性能分析

USE TSQL2012
GO SET STATISTICS IO ON
SET STATISTICS TIME ON SELECT l.id, l.value
FROM [compare].t_left l
WHERE l.value NOT IN
(
SELECT value
FROM [compare].t_right r
)

我们重点看看上述图做了标记的两个重要的地方,最后返回结果集时使用了Merge Anti Semi Join也就是说是上述Merge Join和Right Anti Semi Join的结合,可以说这是一种非常高效的方式,事先通过索引来排序然会获取两个表的结果集。数据库通过Merge Join来迭代两个表的结果集从小值到大值,当然也是通过指针指向二者结果集的当前值然后接着指向下一个值。而Anti Semi Join主要是干什么的呢?前面我们讲过它是半联接,此时数据库引擎只要匹配到t_right表中的值就跳过所有t_left和t_right表其他也同样匹配的同一个值,为什么会跳过呢? 因为此时Stream Aggregate起到了决定性作用(【关于Stream Aggregate前面简单了解了下,感觉理解的还是不够透,写这篇文章时才算是灰常了解了,后续会专门写写Stream Aggregate和Hash Aggregate】)我们知道Stream Aggregate首先需要排序,然后进行分组接着就是聚合,因为我们建立了索引所以就有了排序,接着执行Stream Aggregate进行分组,通过查看Stream Aggregate如下具体信息知道。因为对t_right表中的值进行了分组,所以当进行合并右半联接时,只取组中第一个,其余的自然而然就进行跳过,所以这种方式非常高效,通过索引来进行排序,再通过Stream Aggregate进行分组,最后执行Merge Join(Right Anti Semi Join)。最后我们看到查询仅仅只耗费了0.315秒。

NOT EXISTS性能分析

我们运行如下查询

USE TSQL2012
GO SET STATISTICS IO ON
SET STATISTICS TIME ON SELECT l.id, l.value
FROM [compare].t_left l
WHERE NOT EXISTS
(
SELECT NULL
FROM [compare].t_right r
WHERE r.value = l.value
)

关于其查询耗费时间就不再给出了,其实NOT EXISTS和NOT查询计划和查询时间都是一样的,并没有任何区别,我们之前在单独讨论NOT EXISTS和NOT IN时就已经明确说过,二者在查询列不为NULL的前提下,二者的查询开销是一样的,而将查询列设置为可NULL时,NOT EXISTS的性能远高于NOT IN,这里我们就不过多的讨论了,不明白的童鞋可以看看前面关于二者比较的文章。

LEFT JOIN....IS NULL性能分析

USE TSQL2012
GO SET STATISTICS IO ON
SET STATISTICS TIME ON SELECT l.id, l.value
FROM [compare].t_left l
LEFT JOIN
[compare].t_right r
ON r.value = l.value
WHERE r.value IS NULL

到这里我们知道很显然结果集肯定是一样的,但是查询计划和上述NOT EXISTS、NOT IN有很大的差异,LEFT JOIN...IS NULL首先是使用LEFT JOIN返回所有数据,其中包括重复的,然后再进行过滤,为什么会先进行LEFT JOIN然后再进行Filter呢?因为SQL Server根本无法很智能的识别LEFT JOIN上紧跟着的IS NULL,所以需要两步操作来完成。此时我们需要过滤100万条数据,这是一个非常耗时的工作,所以此时利用非常高效的Hash Match并且是并行的,但是过滤这些值还是要花费很长时间。整个时间花费了0.989秒,其查询耗费时间是NOT EXISTS或者NOT IN的3倍。所以到这里,关于此三者我们可以定下如下这样一个结论。

NOT IN VS NOT EXISTS VS LEFT JOIN..IS NULL结论:当查询缺省值时利用NOT EXISTS和NOT IN是最佳方式,但是前提是二者查询列都不能为NULL,否则使用NOT EXISTS。而LEFT JOIN...IS NULL因其总是不会跳过已经匹配过的值而是利用先返回所有结果集然后过滤的方式,其低效性可想而知。

总结

本节我们比较了NOT EXISTS和NOT IN和LEFT JOIN..IS NULL的性能,最终得出了三者性能分析结论,下一节我们已经确定是最后一篇终极篇比较EXISTS VS IN VS JOIN的性能,简短的内容,深入的理解,我们下节再会。

SQL Server-聚焦NOT IN VS NOT EXISTS VS LEFT JOIN...IS NULL性能分析(十八)的更多相关文章

  1. SQL Server ->> Memory Allocation Mechanism and Performance Analysis(内存分配机制与性能分析)之 -- Minimum server memory与Maximum server memory

    Minimum server memory与Maximum server memory是SQL Server下配置实例级别最大和最小可用内存(注意不等于物理内存)的服务器配置选项.它们是管理SQL S ...

  2. (4.20)SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧

    转自:指尖流淌 https://www.cnblogs.com/zhijianliutang/p/4085546.html SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧 ...

  3. SQL Server的唯一键和唯一索引会将空值(NULL)也算作重复值

    我们先在SQL Server数据库中,建立一张Students表: CREATE TABLE [dbo].[Students]( ,) NOT NULL, ) NULL, ) NULL, [Age] ...

  4. SQL Server-索引故事的遥远由来,原来是这样的?(二十八)

    前言 前段时间工作比较忙,每天回来也时不时去写有关ASP.NET Core的文章,无论是项目当中遇到的也好还是自学的也好都比较严谨的去叙述,喜欢分享,乐于分享这是我一直以来的态度,当然从中也会有些许错 ...

  5. SQL Server-聚焦INNER JOIN AND IN性能分析(十四)

    前言 本节我们来讲讲联接综合知识,我们在大多教程或理论书上都在讲用哪好,哪个性能不如哪个的性能,但是真正讲到问题的实质却不是太多,所以才有了本系列每一篇的篇幅不是太多,但是肯定是我用心去查找许多资料而 ...

  6. SQL Server判断对象是否存在 (if exists (select * from sysobjects )(转)

    1 判断数据库是否存在Sql代码 if exists (select * from sys.databases where name = ’数据库名’)    drop database [数据库名] ...

  7. SQL Server 存储过程中处理多个查询条件的几种常见写法分析,我们该用那种写法

    本文出处: http://www.cnblogs.com/wy123/p/5958047.html 最近发现还有不少做开发的小伙伴,在写存储过程的时候,在参考已有的不同的写法时,往往很迷茫,不知道各种 ...

  8. 强制SQL Server执行计划使用并行提升在复杂查询语句下的性能

        最近在给一个客户做调优的时候发现一个很有意思的现象,对于一个复杂查询(涉及12个表)建立必要的索引后,语句使用的IO急剧下降,但执行时间不降反升,由原来的8秒升到20秒.     通过观察执行 ...

  9. 你所不知道的SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧

    目前SQL Server数据库作为微软一款优秀的RDBMS,其本身启动的时候是很少出问题的,我们在平时用的时候,很少关注起启动过程,或者很少了解其底层运行过程,大部分的过程只关注其内部的表.存储过程. ...

随机推荐

  1. iOS总结_UI层自我复习总结

    UI层复习笔记 在main文件中,UIApplicationMain函数一共做了三件事 根据第三个参数创建了一个应用程序对象 默认写nil,即创建的是UIApplication类型的对象,此对象看成是 ...

  2. ASP.NET MVC 请求路径相关参数的获取

    Request.ApplicationPath / Request.CurrentExecutionFilePath /Home/Index Request.FilePath /Home/Index ...

  3. ASP.NET Aries 入门开发教程7:DataGrid的行操作(主键操作区)

    前言: 抓紧勤奋,再接再励,预计共10篇来结束这个系列. 上一篇介绍:ASP.NET Aries 入门开发教程6:列表数据表格的格式化处理及行内编辑 本篇介绍主键操作区相关内容. 1:什么时候有默认的 ...

  4. 继电器是如何成为CPU的(1)

    继电器是如何成为CPU的(1) ——<穿越计算机的迷雾>整理和总结 究竟是如何设计的电路,具有计算和控制的智力? 这一点也不高深.本系列文章从初中学的最简单的电路图说起,看看能不能从最初的 ...

  5. SuperMap iClient for JavaScript 新手入门

    地理信息系统(英语:Geographic Information System,缩写:GIS)是一门综合性学科,结合地理学与地图学,已经广泛的应用在不同的领域,是用于输入.存储.查询.分析和显示地理数 ...

  6. EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)

    前言 Entity Framework 延伸系列目录 今天我们来聊聊EF的日志记录. 一个好的数据库操作记录不仅仅可以帮你记录用户的操作, 更应该可以帮助你获得效率低下的语句来帮你提高运行效率 废话不 ...

  7. 免费道路 bzoj 3624

    免费道路(1s 128MB)roads [输入样例] 5 7 21 3 04 5 13 2 05 3 14 3 01 2 14 2 1 [输出样例] 3 2 04 3 05 3 11 2 1 题解: ...

  8. PHP设计模式(三)抽象工厂模式(Abstract Factory For PHP)

    一.什么是抽象工厂模式 抽象工厂模式的用意为:给客户端提供一个接口,可以创建多个产品族中的产品对象 ,而且使用抽象工厂模式还要满足以下条件: 系统中有多个产品族,而系统一次只可能消费其中一族产品. 同 ...

  9. 我的屌丝giser成长记-工作篇之B公司

    从A公司跳槽到B公司,岗位还是webgis开发方向,但是具体实现的技术完全变了,从flex转换js,这也是我要离开A公司的最重要的原意之一:A公司的arcgis for flex框架采用了flexvi ...

  10. BPM费控管理解决方案分享

    一.方案概述费用是除经营成本外企业的最主要支出,费用管理是财务管理的核心之一,加强企业内控管理如:费用申请.费用报销.费用分摊.费用审批.费用控制和费用支付等,通过科学有效的管理方法规范企业费用管理, ...