Union All ,Merge,Merge join 区别
本文转自:http://www.cnblogs.com/gudujianxiao/archive/2012/07/17/2594709.html
SSIS Data Flow 中有几个组件可以实现不同数据源的数据合并功能,比如 Merger, Merge Join 和 Union All。它们的功能比较类似,同时也比较容易混淆,下面是对它们之间的区别的对比总结。
下面通过三个 Data Flow 来演示这三个组件的使用以及相关的配置。
测试数据源 -
第一个数据源是一张表
USE BIWORK_SSIS
GO -- Merge demo table
IF OBJECT_ID('DEMO_MG_Customer','U') IS NOT NULL
DROP TABLE DEMO_MG_Customer
GO CREATE TABLE DEMO_MG_Customer
(
CustomerID INT PRIMARY KEY,
CustomerCompany NVARCHAR(255),
CustomerName NVARCHAR(20),
CustomerAddress NVARCHAR(255)
) INSERT INTO DEMO_MG_Customer VALUES
(1,'HFBZG','Allen,Michael','Obere Str. 0123'),
(2,'MLTDN','Hassall, Mark','Avda. de la Constitución 5678'),
(3,'KBUDE','Peoples, John','Mataderos 1000') SELECT * FROM DEMO_MG_Customer
第二个数据源是一个文本文件
ID,Company,CustomerName,Title,Address
1,'NRZBB','Allen,Michael','Sales Representative','Obere Str. 0123'
2,'MLTDN','Hassall, Mark','Owner','Avda. de la Constitución 5678'
3,'KBUDE','Peoples, John','Owner','Mataderos 7890'
4,'HFBZG','Arndt, Torsten','Sales Representative','7890 Hanover Sq.'
5,'HGVLZ','Higginbotham, Tom','Order Administrator','Berguvsvägen 5678'
示例一 - 使用 Merge 来合并数据
- 上面已经说了 Merge 的特点-
- 输入数据源 - 两个
- 输入数据源 - 表或者文件等
- 合并时要求元数据相同,数据类型相同
- 合并前需要排序
合并操作类似于 SQL 语句中的 UNION ALL。
OLE_SRC_Customer - OLE DB Source 中指定的数据源来自 BIWORK_SSIS 数据库中的 dbo.DEMO_MG_Customer 表。
表中的 5 个列都将作为输出列向下输出。
FF_SRC_Customer (Flat File Source) 的 Flat File Connection Manager 指向文本文件源。并且要注意 Text qualifier 是', 因为要注意到文本文件中位于 ' ' 之间的才是真正要处理的文本。
1,'NRZBB','Allen,Michael','Sales Representative','Obere Str. 0123'
并且指明文本文件中的第一行是列标题。
逗号分割列
在这里要注意的是文本文件中 ID 的数据类型指定 DT_I4 来映射 SQL Server 数据库中的INT 类型,否则两个数据源一旦有一个列数据类型不一致的话,那么合并操作时就会出现错误。
其它字符串用 DT_WSTR 即可,因为要和数据库中的 NVARCHAR 数据类型匹配。
注意在 Flat File Source 向下输出的时候并没有选择 Title, 因为这一列在 Input Table Source 中并不存在。在合并两个来自不同数据源的时候,我们要求两边的元数据一致,即列的数量和类型也应该一致。
因为本身 ID 就是有序的,所以为了演示的效果选择 CustomerName 作为排序列,两边的源的拍序列也应该选择一致。
Merger Transformation 列出了输出的列,两个输入源并且显示了它们的排序列,最终输出的结果也会按照 CustomerName 排序的结果来输出。
Merge 之后来自于两个不同数据源的数据就合并到了一起,并且 CustomerID = 2 的数据分别来自两个数据源,内容也是一致的,但并没有在合并的时候删除重复的数据,这类似于 SQL 语句中的 UNION ALL 的操作,保留了重复项。
示例二 - 使用 Merge Join 组件合并数据
Merge Join 类似于 SQL 中的 Full/Left/Inner Join 等操作,因为不需要两边数据源的元数据一致。但是,它也要求左右两边的数据源排序,并且排序列必须包含后面使用到的 JOIN 列。
前面的配置和上一个例子中一样,只是排序列改成了 CustomerID,只看 Merge Join 部分。
除了 Inner Join 外,还有 Full Join 和 Left Outer Join 等同于 SQL 中的 Inner Join/Full Join/Left Join 等操作。
看上面图片中显示了左右两边的数据源,其中 Join Key 必须包含在排序列中。在左边的表数据源中有4个输出列,与右边文件中的 Title 输出列共同组成了5个输出列。
如果使用 SQL 语句来表示这里的逻辑,可以理解成-
SELECT tbl.CustomerID,
tbl.CustomerCompany,
tbl.CustomerName,
tbl.CustomerAddress,
ff.Title
FROM ST_TBL_Customer AS tbl
INNER JOIN ST_FF_Customer AS ff
ON tbl.CustomerID = ff.ID
从这里看出 Inner Join 能关联上3条数据,其中 Title 列来源于文件数据源。
在这里,也可以使用 Merge Join 组件完成对已存在的数据进行更新,对不存在的数据进行插入操作。比如可以使用 Left Outer Join, 假设以左表为目标表的话,那么就能够利用关联上 ID 的右文件数据源来更新左表,关联不上的就作为新数据插入到左表中。只需要在 Merge Join 下加一个 Conditional Split 组件来判断即可,可以参考我的另一篇文章 -
SSIS 系列 - Lookup 组件的使用与它的几种缓存模式 - Full Cache, Partial Cache, NO Cache
示例三 - 使用 UNION ALL 组件合并数据
UNION ALL 组件与上面两个组件最大的区别就是,一可以合并两个以上的数据源,二是不需要对数据源进行排序。
这个示例中有三个数据源,前两个和上面示例中的配置一样,第三个数据源和第二个数据源实质上相同,都是指向同一个数据表。
直接看 UNION ALL 组件的配置,非常的简单。
看到输出列了吗? 默认情况下将第一个文件数据源的列作为默认的整个组件的输出列,如果后面的数据源没有这些列的话,那么就忽略掉,其它的列再一一设置匹配一下,当然数据类型应该一致。
输出的结果如下,有重复的数据并且也未排序。
通过这样的对比,就能看到三个组件各自不同的特点。
简单的可以归纳一下何时应该选择 Merge, Merge Join 和 Union All 组件来合并不同数据源的数据呢?
- 如果有两个以上的数据源 - UNION ALL
- 如果只有两个数据源,并且是从两个不同数据源基于一些关联条件各取一部分数据 - Merge Join
- 如果只有两个数据源,目的为了合并而非关联 - UNION ALL/Merge
- 如果只有两个数据源,目的只为了合并但不需要输出的结果排序 - UNION ALL
- 如果只有两个数据源,目的只为了合并但需要输出的结果排序 - Merge
Asynchronous Transformation VS Synchronous Transformation
当然,除此之外还有些细节需要知道的是 - 尽量避免使用 Sort 排序组件,原因在于 Sort 排序组件被称之为 Asynchronous Transformation。
Asynchronous Transformation 非同步转换 - Blocked Transformation 阻塞转换。Sort 排序组件就属于这一类,和它相同的还有 Pivot 组件。
它们处理数据的过程是先从上游数据源中抽取所有数据,再开始处理排序,全部排序完成之后再产生输出。这样的过程极大的消耗了内存并且使得整个处理的过程变得缓慢。
相对于这类组件,有一类组件是属于 Synchronous Transformation 同步转换,比如:
- Derived Column
- Copy Column
- Data Conversion
这类组件基本上是从数据源一条一条的取,一条一条的处理并同时输出给下游转换组件。
所以在上面的几个示例中,更优的选择应该是在 OLE DB Source 的操作中使用 SELECT 语句加上排序操作来代替直接使用表或者视图,这样避免转换阻塞。
因此对示例一做出一些修改,去掉中间的排序组件。
在 OLE_SRC_Customer 中使用 SELECT 语句加上排序操作使得输出是已经排好序的结果。
SELECT CustomerID,
CustomerCompany,
CustomerName,
CustomerAddress
FROM dbo.DEMO_MG_Customer
ORDER BY CustomerName
但是再次连接到 Merge 组件上时会发生错误,因为你还要通知一下 Merge 组件你是如何排序的。
右键 OLE_SRC_Customer 选择 Advanced Editor,在 Input and Output Properties 这里修改一下 IsSorted 属性,设置为 True, 默认是 False。 这样就告诉了下游转换组件,这里的结果是已经排好序的。
同时还需要指定如何排序,按照哪些列来排的序。因为在示例 Merge 中我们选择的是 Customer Name, 因此这里将它的 0 修改为1。 0 表示是不排序的,1 表示是第 一个排序位,这里应该按照 ORDER BY 后面的列顺序来设置,第二个排序列就设置为 2, 依此类推。
修改完毕后,再运行一下第一个示例,结果是一样的
这里的数据量比较少,可以试一下10W级,100W级 以上使用 Sort 组件和不使用 Sort 组件的差别来体会一下这两种处理方式的不同。
Union All ,Merge,Merge join 区别的更多相关文章
- 微软BI 之SSIS 系列 - Merge, Merge Join, Union All 合并组件的使用以及Sort 排序组件同步异步的问题
开篇介绍 SSIS Data Flow 中有几个组件可以实现不同数据源的数据合并功能,比如 Merger, Merge Join 和 Union All.它们的功能比较类似,同时也比较容易混淆,下面是 ...
- python merge、join、concat用法与区别
由于合并变化较大,以后函数可能会修改,只给出一些例子作为参考 总结: merge.join 1.当没有索引时:merge.join为按照一定条件合并 2.当有索引.并按照索引合并时,得到结果为两者混 ...
- SQL Tuning 基础概述06 - 表的关联方式:Nested Loops Join,Merge Sort Join & Hash Join
nested loops join(嵌套循环) 驱动表返回几条结果集,被驱动表访问多少次,有驱动顺序,无须排序,无任何限制. 驱动表限制条件有索引,被驱动表连接条件有索引. hints:use_n ...
- oracle表连接------>排序合并连接(Merge Sort Join)
排序合并连接 (Sort Merge Join)是一种两个表在做连接时用排序操作(Sort)和合并操作(Merge)来得到连接结果集的连接方法. 对于排序合并连接的优缺点及适用场景例如以下: a,通常 ...
- Union和Union All到底有什么区别
以前一直不知道Union和Union All到底有什么区别,今天来好好的研究一下,网上查到的结果是下面这个样子,可是还是不是很理解,下面将自己亲自验证: Union:对两个结果集进行并集操作,不包括重 ...
- left join ,right join ,inner join ,cross join 区别
left join ,right join ,inner join ,cross join 区别(参考:http://zhidao.baidu.com/link?url=gpOl9HXZR0OrQuy ...
- C和C++中结构体(struct)、联合体(union)、枚举(enum)的区别
C++对C语言的结构.联合.枚举 这3种数据类型进行了扩展. 1.C++定义的结构名.联合名.枚举名 都是 类型名,可以直接用于变量的声明或定义.即在C++中定义变量时不必在结构名.联合名.枚举名 前 ...
- 并发编程 - 进程 - 1.互斥锁/2.模拟抢票/3.互斥锁与join区别
1.互斥锁: 互斥锁:Lock 原理就是把并发变成串行,一个一个运行,不错乱,但效率低 保证多个进程修改一块数据时,大家是一个一个修改,不错乱 mutex.acquire() mutex.releas ...
- inner join ,left join ,right join区别
inner join ,left join ,right join区别 left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录 right join(右联接) 返回包括右表中 ...
随机推荐
- 无法安装 golang.org/x/tools/的库
安装godep 官方的安装文档是使用go get github.com/tools/godep,很可惜,因为“网络”问题会报一个找不到golang.org/x/tools/go/vcs的错误. 而ht ...
- 绝不要在构造函数和析构过程中调用virtual函数
下面是一个用来塑模股市交易的类: derived的类的构造函数被调用,但是首先得调用基类Transaction的构造函数,但是在后面还得调用virrual函数,这个时候子类的对象的构造还没有完成,那么 ...
- mysql 控制台环境下查询中文数据乱码,插入、更新中文数据不成功
mysql 控制台环境下查询中文数据乱码,插入.更新中文数据不成功 登录mysql密码是加入编码参数--default-character-set,中文用gbk mysql -uroo ...
- Thrift安装介绍
一.简介 1.语言库要求 因为thrift支持多语言.所以编译thrift源代码的过程中,会用到该语言的一些类库.如c++的boost.java的jdk等. 那么,在安装thrift过程中,须要对各种 ...
- AVL平衡树的插入例程
/* **AVL平衡树插入例程 **2014-5-30 11:44:50 */ avlTree insert(elementType X, avlTree T){ if(T == NULL){ T = ...
- Mataplotlib绘图和可视化
Mataplotlib是一个强大的python绘图和数据可视化工具包 安装方法:pip install matplotlib 引用方法:import matplotlib.pyplot as plt ...
- linux c 网络编程:用域名获取IP地址或者用IP获取域名 网络地址转换成整型 主机字符顺序与网络字节顺序的转换
用域名获取IP地址或者用IP获取域名 #include<stdio.h> #include<sys/socket.h> #include<netdb.h> int ...
- 你必须了解的java内存管理机制(一)-运行时数据区
前言 本打算花一篇文章来聊聊JVM内存管理机制,结果发现越扯越多,于是分了四遍文章(文章讲解JVM以Hotspot虚拟机为例,jdk版本为1.8),本文为其中第一篇.from 你必须了解的java内存 ...
- dsp-asic-fpga
DSP是在模拟信号变换成数字信号以后进行高速实时处理的专用处理器,它采用的是哈佛设计,即数据总线和地址总线分开,使程序和数据分别存储在两个分开的空间,允许取指令和执行指令完全重叠,也就是说在执行上一条 ...
- JavaSE 文件递归之删除&获取文件夹文件夹中全部的以.jpg的文件的绝对路径
1.递归删除文件 假设一个文件夹以下还有子文件夹,进行删除的话会 报错,这个时候要使用递归的方式来删除这个文件文件夹中的全部文件以及文件夹 package cn.itcast.digui; impor ...