设为首页 收藏本站
查看: 714|回复: 0

[经验分享] SQL Server-聚焦INNER JOIN AND IN性能分析(十四)

[复制链接]

尚未签到

发表于 2017-7-13 06:36:04 | 显示全部楼层 |阅读模式
前言
  本节我们来讲讲联接综合知识,我们在大多教程或理论书上都在讲用哪好,哪个性能不如哪个的性能,但是真正讲到问题的实质却不是太多,所以才有了本系列每一篇的篇幅不是太多,但是肯定是我用心去查找许多资料而写出,简短的内容,深入的理解,Always to review the basics。

初次探讨INNER JOIN和IN性能分析
  接下来我们看第一篇联接综合知识讲解INNER JOIN和IN的比较分析,我们通过创建表来看INNER JOIN。
  创建测试表1



CREATE TABLE Table1  (
id INT IDENTITY PRIMARY KEY,
SomeColumn CHAR(4),
Filler CHAR(100)
)
  插入测试数据



Insert into Table1(SomeColumn) Values (1),(2),(3),(4),(5)
  创建测试表2并插入数据



USE TSQL2012
GO
CREATE TABLE Table2  (IntCol int)
Insert into Table2 (IntCol) Values (1),(2),(2),(3),(4),(5),(5)
  接下来我们对测试表1和测试表2中的SomeColumn和IntCol进行JOIN



USE TSQL2012
GO
SELECT *
FROM Table1 b
INNER JOIN Table2 s ON b.SomeColumn = s.IntCol
DSC0000.png

  此时我们看到两个测试表中都返回7行数据,因为在测试表2中有重复的数据都匹配上所有测试表1返回所有数据。此时我们再来看看IN的查询



USE TSQL2012
GO
SELECT *
FROM Table1
WHERE SomeColumn IN (Select IntCol FROM Table2)
DSC0001.png

  此时则返回5条数据,从这里我们知道INNER JOIN和IN还是有很大的区别,但是若在测试表2中没有重复的数据,同时在测试表2中没有需要的列,此时则查询出的数据和测试表1是一样的,此时二者在性能上有什么区别呢?接下来我们在创建大量数据的前提下来进行测试看看。
  创建两个测试表



CREATE TABLE BigTable (
id INT IDENTITY PRIMARY KEY,
SomeColumn UNIQUEIDENTIFIER NOT NULL,
Filler CHAR(100)
)
CREATE TABLE SmallerTable (
id INT IDENTITY PRIMARY KEY,
LookupColumn UNIQUEIDENTIFIER NOT NULL,
SomeArbDate DATETIME DEFAULT GETDATE()
)
  在BigTable表SomeColumn列中插入100万条数据



INSERT INTO BigTable (SomeColumn)
SELECT NEWID()
FROM dbo.Nums
WHERE n<1000001
  取出BigTable中的25%数据插入到SmallerTable表LookupColumn列中



USE TSQL2012
GO
INSERT INTO SmallerTable (LookupColumn)
SELECT DISTINCT SomeColumn
FROM BigTable TABLESAMPLE (25 PERCENT)
  这里我们分三种情况来测试。
  (1)未建立索引比较INNER和JOIN



SELECT BigTable.ID, SomeColumn
FROM BigTable
WHERE SomeColumn IN (SELECT LookupColumn FROM dbo.SmallerTable)
SELECT BigTable.ID, SomeColumn
FROM BigTable
INNER JOIN SmallerTable ON dbo.BigTable.SomeColumn = dbo.SmallerTable.LookupColumn
DSC0002.png

DSC0003.png

  从上看出此时在无论是查询开销还是IO上均没有什么差异,下面我们再来看看建立索引的情况
  (2)建立非唯一非聚集索引比较INNER JOIN和IN



CREATE INDEX idx_BigTable_SomeColumn ON BigTable (SomeColumn)
CREATE INDEX idx_SmallerTable_LookupColumn ON SmallerTable (LookupColumn)
DSC0004.png

DSC0005.png

  此时我们发现在建立非唯一非聚集索引的情况二者在查询开销上开始有了比较大的差异,INNER JOIN的开销是IN的两倍而IO几乎是等同的。
  (3)建立唯一非聚集索引比较INNER JOIN和IN



CREATE UNIQUE INDEX idx_BigTable_SomeColumn ON BigTable (SomeColumn)
CREATE UNIQUE INDEX idx_SmallerTable_LookupColumn ON SmallerTable (LookupColumn)
DSC0006.png

  此时为何索引变为唯一聚集索引二者性能开销却一致了呢?有点纳闷,同时到这里为止是不是说明IN的查询性能比JOIN的性能更好呢,完全颠覆我们的想法,在本文前言我们讨论过在教程中都会给出大部分JOIN比EXISTS性能好,而EXISTS比IN性能好,凡是还是动手实践,亲自验证才是王道,我们只能得出一般性结论:一般来说,JOIN比EXISTS性能好,而EXISTS比IN性能好仅此而已。这都是一般性情况,本系列需要讲述的是什么时候应该用EXISTS,什么时候应该用JOIN,还有什么时候应该用IN,后续内容会陆续讨论这些内容。好了,有点跑题了,上述我们通过100万条数据得出IN的性能接近是INNER JOIN性能的两倍,完全出乎你我的意料,带着这个疑问,接下来我们进一步进行探讨。

进一步探讨INNER JOIN和IN性能分析
  上述在SmallerTable表从BigTable表中取出的25%的数据都是唯一的,接下来我们将这25%数据的一部分设置为重复的。我们随便从BigTable表中取出SomeColumn这列的数据,然后将SmallerTable表中的LookupColumn这列的数据设置重复的10000条,如下



USE TSQL2012
GO
UPDATE dbo.SmallerTable SET LookupColumn = '0067cb6c-64e1-46cc-b7f2-334a7dd812ff'
WHERE id>=1 AND id<=10000
  此时我们查询包括重复的这10000条



USE TSQL2012
GO
SELECT BigTable.ID, SomeColumn
FROM BigTable
WHERE SomeColumn IN (SELECT LookupColumn FROM dbo.SmallerTable)
SELECT BigTable.ID, SomeColumn
FROM BigTable
INNER JOIN SmallerTable ON dbo.BigTable.SomeColumn = dbo.SmallerTable.LookupColumn
DSC0007.png

  此时结果还是IN性能比INNER JOIN性能要接近一半,接下来我们在查询SmallerTable表时将重复的LookupColumn列数据去除,此时我们查询变为如下:



USE TSQL2012
GO
SELECT BigTable.ID, SomeColumn
FROM BigTable
WHERE SomeColumn IN (SELECT LookupColumn FROM dbo.SmallerTable)
SELECT BigTable.ID, SomeColumn
FROM BigTable
INNER JOIN (SELECT DISTINCT LookupColumn FROM dbo.SmallerTable) AS s
ON s.LookupColumn = dbo.BigTable.SomeColumn
DSC0008.png

  终于查询开销和上述不一样了,此时二者查询性能开销是一致的,相信到了这里我们应该很清楚了。通过上述大量篇幅的贴图和比较我们可以得出INNER JOIN和IN的性能开销使用场景,当我们在初步探讨INNER JOIN和IN的性能分析时,当建立非唯一聚集索引时IN性能接近是INNER JOIN的两倍,而当建立唯一聚集索引时,此时性能开销一致,不免有点纳闷,当我们继续向下探讨时终于明白了这个原因,至此我们最终得出INNER JOIN和IN的性能开销结论。
  INNER JOIN和IN性能开销结论:当INNER JOIN表中列数据是唯一的,此时INNER JOIN和IN的性能开销是相同的,当INNER JOIN表中列数据是重复的,此时IN性能要INNER JOIN要好。

总结
  本节我们详细叙述了INNER JOIN和IN的性能分析,最终得出一致性结论,下节我们开始讨论NOT EXISTS和NOT IN性能分析,简短的内容,深入的理解,我们下节再会,good night。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-393328-1-1.html 上篇帖子: SQL Server书籍整理 下篇帖子: SQL Server-分页方式、ISNULL与COALESCE性能分析(八)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表