1概述
Merge join 合并连接。两个集合进行merge join,需要有一个等值的条件,然后需要两个已排序好的集合。

2 one-to-many与many-to-many
2.1 One-to-many
当参与merge join的两个集合中,其中一个集合在等值条件上是具有唯一性(如SELECT * FROM T1 INNER JOIN T2 ON T1.A=T2.B,如果T1在A列上具有唯一性),那么即为one-to-many。主要步骤为:首先从两个集合中各取出一条记录进行比较,如果符合join条件,那么取出该行;否则将值小记录从集合中移除,然后取值小集合的下一行,继续比较。
2.2 many-to many
当参与merge join的两个集合中,没有一个集合在等值条件上具有唯一性时,则采用many-to-many(SELECT * FROM T1 INNER JOIN T2 ON T1.A=T2.B,当列A与列B都不具有唯一性)。主要步骤为:在A和B中都存在A1,A2..An,B1,B2..Bn,那么正常情况下需要为A的每一条记录(A1,A2..An)都要将B中的B1,B2..Bn读取出来,这样浪费性能。所在数据库在处理时,将B中的匹配行储存在tempdb中,如果A中的下一行相等,则读取tempdb中的内容,否则删除tempdb中的数据。
2.3 one-to-many与many-to-many的比较
很显然,one-to-many的效率更高,因为它不需要临时表。那么如何让查询优化器知道我们其中某个集合具有唯一性呢。方法一是:建立聚集索引;二是如distinct、group by操作符。

3排序与索引
数据库几个大的操作之一就是大表的排序,所以使用merge join如果表数据量比较大,并且无索引,那么并不适合merge join。所以当数据量很大,就需要为其添加索引。

4示例
测试数据

View Code

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[GoodsType]'))
DROP TABLE [dbo].[GoodsType]
GO
--商品类型表
CREATE TABLE dbo.[GoodsType]
(id int,good_type_name nvarchar(50)
);INSERT INTO dbo.GoodsType
SELECT 1,'服装'
UNION ALL
SELECT 2,'数码'
UNION ALL
SELECT 3,'家电'IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Goods]'))
DROP TABLE [dbo].[Goods]
GO
--商品类型表
CREATE TABLE dbo.[Goods]
(id int,good_name nvarchar(50),good_type int
);INSERT INTO dbo.Goods
SELECT 1,'ADT恤',1
UNION ALL
SELECT 2,'AD外套',1
UNION ALL
SELECT 3,'T002电视',2
UNION ALL
SELECT 4,'海尔洗衣机',2
UNION ALL
SELECT 5,'HP222',3

4.1
未建任何索引,执行SQL

View Code

SET STATISTICS PROFILE ON
SELECT *
FROM Goods AS GINNER JOIN GoodsType AS GT ON G.good_type=GT.id
OPTION(MERGE JOIN)

结果:

说明
1>未建立索引时,需要为两个集合进行排序;
2>虽然在连接条件上唯一,但是未建唯一聚集索引时,为多对多的连接;

4.2
建立非聚集索引,执行SQL

View Code

CREATE CLUSTERED INDEX GT ON GOODSTYPE(ID)
CREATE CLUSTERED INDEX G ON GOODS(good_type)SET STATISTICS PROFILE ON
SELECT *
FROM Goods AS GINNER JOIN GoodsType AS GT ON G.good_type=GT.id
OPTION(MERGE JOIN)

结果:

说明:
1>建立索引后,执行merge join无排序的开销
2>虽然两个集合都建立了索引,并且连接的关键字也无重复,但还是多对多的连接,因为优化器不知道它是唯一的。

4.3
为其中一个集合建立唯一聚集索引,执行SQL

View Code

DROP INDEX GT ON GOODSTYPE
CREATE UNIQUE CLUSTERED INDEX GUT ON GOODSTYPE(ID)SET STATISTICS PROFILE ON
SELECT *
FROM Goods AS GINNER JOIN GoodsType AS GT ON G.good_type=GT.id
OPTION(MERGE JOIN)

结果

说明:
1>为其中的一个集合建立唯一聚集索引时,此时的连接为一对一的连接(执行计划中无一对一连接的概念)

5总结
当不适合使用nested join时,可以考虑使用merge join。在使用merge join时,需要注意两个概念:一是排序,最好是索引排序,否则大数据量的实时排序会增加太多的成本;二是连接方式,是一对多还是多对多,如果关键字不重复,可以建立唯一聚集索引,即尽量使用一对多的连接。

SQL JOIN --Merge Join相关推荐

  1. HASH JOIN ,MERGE JOIN ,NESTED LOOP用法效率比较

    概述: NESTED LOOP: 对于被连接的数据子集较小的情况,嵌套循环连接是个较好的选择.在嵌套循环中,内表被外表驱动,外表返回的每一行都要在内表中检索找到与它匹配的行,因此整个查询返回的结果集不 ...

  2. 多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP

    在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式. 之前打算在sqlplus中用执行计划的,但是格式看起来有点乱,就用Toad 做了3个截图. 从3张图里我们看到了几点 ...

  3. SQL优化(一) Merge Join vs. Hash Join vs. Nested Loop

    本文介绍了Merge Join,Hash Join,Nested Loop这三种数据库Join方式的工作原理,并通过实验进一步说明了其适用范围. 原创文章,转载请务必将下面这段话置于文章开头处(保留超 ...

  4. MS SQL SERVER 中merge join合并连接介绍(转)

    1概述 Merge join 合并连接.两个集合进行merge join,需要有一个等值的条件,然后需要两个已排序好的集合. 2 one-to-many与many-to-many 2.1 One-to ...

  5. SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join?

    SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join? SQL的连接(join)有哪些常见形式? sql连接查询:把多张表的列组合在一起,产 ...

  6. 理解原理的重要性 - 论PostgreSQL merge join 成本评估陷阱 含case

    背景 PostgreSQL支持三种JOIN的方法,nestloop, merge, hash. 这三种JOIN方法的差别和原理可以参考 https://www.postgresql.org/docs/ ...

  7. TiDB 源码阅读系列文章(十五)Sort Merge Join

    2019独角兽企业重金招聘Python工程师标准>>> 什么是 Sort Merge Join 在开始阅读源码之前, 我们来看看什么是 Sort Merge Join (SMJ),定 ...

  8. 表的连接方式:NESTED LOOP、HASH JOIN、SORT MERGE JOIN

    表连接方式及使用场合 NESTED LOOP 对于被连接的数据子集较小的情况,nested loop连接是个较好的选择.nested loop就是扫描一个表,每读到一条记录,就根据索引去另一个表里面查 ...

  9. SQL 中 left join 的底层原理(各种JOIN的复杂度探究)

    01. 前言 写过或者学过 SQL 的人应该都知道 left join,知道 left join 的实现的效果,就是保留左表的全部信息,然后把右表往左表上拼接,如果拼不上就是 null.除了 left ...

最新文章

  1. This和Super关键字的对比
  2. GAN还有这种操作!谷歌大脑和X实验室利用模拟条件和域适应提高机器抓取效率(附论文)
  3. Android启动屏全屏显示
  4. ansible普通用户部署K8s要点
  5. 题目1005:Graduate Admission(结构体排序)
  6. AI编译器与传统编译器的联系与区别
  7. IOS 定义手势监听器详解,利用 UIGestureRecognizer 进行捏合、旋转、平移、点击、长按手势事件响应
  8. linux中查看和开放端口
  9. 使用Spring JDBC时遇到的Software caused connection abort: recv failed问题
  10. practice:在win2008R2上使用(NLB)网络负载均衡
  11. mysql中dint_mysql常用操作——数据库和表的操作1(共2页)
  12. dorado 7 数据库配置
  13. 信息学奥赛一本通(c++):1125:矩阵乘法
  14. jdk8特性 lambda表达式
  15. 人生「价值」的三个关键词|《价值》
  16. DR、BDR、SBR、ASBR等名词的解释和原理
  17. 利用客户支持建立忠诚度和竞争优势
  18. 【专栏】国内外物联网平台初探(篇三:QQ物联·智能硬件开放平台)
  19. 3D 中的方位与角位移(旋转矩阵、欧拉角、四元数)
  20. swift UI专项训练21 网页浏览器

热门文章

  1. 14、mybatis多表关联查询 association定义关联对象封装规则及懒加载
  2. linux分析字节序的分类及特点,计算机中的字节序详解 分类: 【Linux/Windows操作系统】 2015-01-07 21:54 97人阅读 评论(0) 收藏...
  3. 「神策客景」全面升级,懂客户,更懂你
  4. spring boot 日志文件配置(logback-spring.xml)亲测可用!
  5. 在Linux上自动调整屏幕亮度保护眼睛
  6. word操作快捷键记录
  7. 用Android访问本地站点---(localhost,10.0.2.2)要区别
  8. 解耦HTML、CSS和JavaScript
  9. 注意Hibernate4在开发当中的一些改变
  10. CLR Via CSharp读书笔记(14):字符、字符串和文本处理