SQL JOIN --Merge Join
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示例
测试数据
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
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
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
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相关推荐
- HASH JOIN ,MERGE JOIN ,NESTED LOOP用法效率比较
概述: NESTED LOOP: 对于被连接的数据子集较小的情况,嵌套循环连接是个较好的选择.在嵌套循环中,内表被外表驱动,外表返回的每一行都要在内表中检索找到与它匹配的行,因此整个查询返回的结果集不 ...
- 多表连接的三种方式详解 HASH JOIN MERGE JOIN NESTED LOOP
在多表联合查询的时候,如果我们查看它的执行计划,就会发现里面有多表之间的连接方式. 之前打算在sqlplus中用执行计划的,但是格式看起来有点乱,就用Toad 做了3个截图. 从3张图里我们看到了几点 ...
- SQL优化(一) Merge Join vs. Hash Join vs. Nested Loop
本文介绍了Merge Join,Hash Join,Nested Loop这三种数据库Join方式的工作原理,并通过实验进一步说明了其适用范围. 原创文章,转载请务必将下面这段话置于文章开头处(保留超 ...
- MS SQL SERVER 中merge join合并连接介绍(转)
1概述 Merge join 合并连接.两个集合进行merge join,需要有一个等值的条件,然后需要两个已排序好的集合. 2 one-to-many与many-to-many 2.1 One-to ...
- SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join?
SQL的连接(join)有哪些常见形式?解释一下?解释 SQL 的 left join 和 right join? SQL的连接(join)有哪些常见形式? sql连接查询:把多张表的列组合在一起,产 ...
- 理解原理的重要性 - 论PostgreSQL merge join 成本评估陷阱 含case
背景 PostgreSQL支持三种JOIN的方法,nestloop, merge, hash. 这三种JOIN方法的差别和原理可以参考 https://www.postgresql.org/docs/ ...
- TiDB 源码阅读系列文章(十五)Sort Merge Join
2019独角兽企业重金招聘Python工程师标准>>> 什么是 Sort Merge Join 在开始阅读源码之前, 我们来看看什么是 Sort Merge Join (SMJ),定 ...
- 表的连接方式:NESTED LOOP、HASH JOIN、SORT MERGE JOIN
表连接方式及使用场合 NESTED LOOP 对于被连接的数据子集较小的情况,nested loop连接是个较好的选择.nested loop就是扫描一个表,每读到一条记录,就根据索引去另一个表里面查 ...
- SQL 中 left join 的底层原理(各种JOIN的复杂度探究)
01. 前言 写过或者学过 SQL 的人应该都知道 left join,知道 left join 的实现的效果,就是保留左表的全部信息,然后把右表往左表上拼接,如果拼不上就是 null.除了 left ...
最新文章
- This和Super关键字的对比
- GAN还有这种操作!谷歌大脑和X实验室利用模拟条件和域适应提高机器抓取效率(附论文)
- Android启动屏全屏显示
- ansible普通用户部署K8s要点
- 题目1005:Graduate Admission(结构体排序)
- AI编译器与传统编译器的联系与区别
- IOS 定义手势监听器详解,利用 UIGestureRecognizer 进行捏合、旋转、平移、点击、长按手势事件响应
- linux中查看和开放端口
- 使用Spring JDBC时遇到的Software caused connection abort: recv failed问题
- practice:在win2008R2上使用(NLB)网络负载均衡
- mysql中dint_mysql常用操作——数据库和表的操作1(共2页)
- dorado 7 数据库配置
- 信息学奥赛一本通(c++):1125:矩阵乘法
- jdk8特性 lambda表达式
- 人生「价值」的三个关键词|《价值》
- DR、BDR、SBR、ASBR等名词的解释和原理
- 利用客户支持建立忠诚度和竞争优势
- 【专栏】国内外物联网平台初探(篇三:QQ物联·智能硬件开放平台)
- 3D 中的方位与角位移(旋转矩阵、欧拉角、四元数)
- swift UI专项训练21 网页浏览器
热门文章
- 14、mybatis多表关联查询 association定义关联对象封装规则及懒加载
- linux分析字节序的分类及特点,计算机中的字节序详解 分类: 【Linux/Windows操作系统】 2015-01-07 21:54 97人阅读 评论(0) 收藏...
- 「神策客景」全面升级,懂客户,更懂你
- spring boot 日志文件配置(logback-spring.xml)亲测可用!
- 在Linux上自动调整屏幕亮度保护眼睛
- word操作快捷键记录
- 用Android访问本地站点---(localhost,10.0.2.2)要区别
- 解耦HTML、CSS和JavaScript
- 注意Hibernate4在开发当中的一些改变
- CLR Via CSharp读书笔记(14):字符、字符串和文本处理