下面的场景演示了Merge Join和Lookup之间的性能差异。这里使用的数据是一对一联接,这是它们之间唯一可以比较的共同场景。 1.我有三个名为dbo.ItemPriceInfo、dbo.ItemDiscountInfo和dbo.ItemAmount的表。SQL脚本部分提供了这些表的创建脚本。 1.表dbo.ItemPriceInfo和dbo.ItemDiscountInfo都有13,349,729行。这两个表都将ItemNumber作为公用列。ItemPriceInfo包含价格信息,ItemDiscountInfo包含折扣信息。屏幕快照#2显示了每个表中的行数。屏幕快照#3显示了前6行,以给予表中存在的数据。 1.我创建了两个SSIS包来比较合并联接转换和查找转换的性能。这两个包都必须从表dbo.ItemPriceInfo和dbo.ItemDiscountInfo获取信息,计算总量并将其保存到表dbo.ItemAmount。 1.第一个包使用了Merge Join转换,并在该转换内部使用INNER JOIN来合并数据。屏幕快照#4和#5显示了示例包执行和执行持续时间。执行基于合并联接转换的包花费了**05分钟14秒719毫秒。 1.第二个包使用了具有完全缓存(默认设置)的Lookup转换。屏幕快照#6和#7显示了示例包执行和执行持续时间。执行基于查找转换的包花费了11分钟03秒610毫秒。您可能会遇到警告消息信息:The buffer manager has allocated nnnnn bytes, even though the memory pressure has been detected and repeated attempts to swap buffers have failed.这里有一个link,讨论如何计算查找缓存大小。在此包执行期间,尽管数据流任务完成得更快,但管道清理花费了大量时间。 1.这并不意味着查找转换是不好的。只是它必须被明智地使用。我经常在我的项目中使用它,但我也不会每天处理1000多万行的查找。通常,我的作业处理200万到300万行,因此性能非常好。最多1000万行,两者的表现都一样好。2大多数时候我注意到瓶颈是目标组件而不是转换。3你可以通过拥有多个目标来克服这个问题。4这里**是一个展示多个目标实现的例子。 1.屏幕截图#8显示了所有三个表中的记录计数。屏幕截图#9显示了每个表中的前6个记录。
SQL脚本:
CREATE TABLE [dbo].[ItemAmount](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ItemNumber] [nvarchar](30) NOT NULL,
[Price] [numeric](18, 2) NOT NULL,
[Discount] [numeric](18, 2) NOT NULL,
[CalculatedAmount] [numeric](18, 2) NOT NULL,
CONSTRAINT [PK_ItemAmount] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO
CREATE TABLE [dbo].[ItemDiscountInfo](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ItemNumber] [nvarchar](30) NOT NULL,
[Discount] [numeric](18, 2) NOT NULL,
CONSTRAINT [PK_ItemDiscountInfo] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO
CREATE TABLE [dbo].[ItemPriceInfo](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ItemNumber] [nvarchar](30) NOT NULL,
[Price] [numeric](18, 2) NOT NULL,
CONSTRAINT [PK_ItemPriceInfo] PRIMARY KEY CLUSTERED ([Id] ASC)) ON [PRIMARY]
GO
7条答案
按热度按时间xzabzqsa1#
屏幕截图#1显示了
Merge Join transformation
和Lookup transformation
之间的几个区别点。关于查找:
如果您想根据源1的输入在源2中查找匹配的行,并且您知道每个输入行只有一个匹配,那么我建议使用查找操作。例如,您的
OrderDetails
表,并且您想查找匹配的Order Id
和Customer Number
,那么查找是一个更好的选择。关于合并联接:
如果要执行连接,例如从
Address
表中为Customer
表中的给定客户提取所有地址(Home、Work、Other),则必须使用Merge Join,因为客户可以有一个或多个地址与之关联。比较示例:
下面的场景演示了
Merge Join
和Lookup
之间的性能差异。这里使用的数据是一对一联接,这是它们之间唯一可以比较的共同场景。1.我有三个名为
dbo.ItemPriceInfo
、dbo.ItemDiscountInfo
和dbo.ItemAmount
的表。SQL脚本部分提供了这些表的创建脚本。1.表
dbo.ItemPriceInfo
和dbo.ItemDiscountInfo
都有13,349,729行。这两个表都将ItemNumber作为公用列。ItemPriceInfo包含价格信息,ItemDiscountInfo包含折扣信息。屏幕快照#2显示了每个表中的行数。屏幕快照#3显示了前6行,以给予表中存在的数据。1.我创建了两个SSIS包来比较合并联接转换和查找转换的性能。这两个包都必须从表
dbo.ItemPriceInfo
和dbo.ItemDiscountInfo
获取信息,计算总量并将其保存到表dbo.ItemAmount
。1.第一个包使用了
Merge Join
转换,并在该转换内部使用INNER JOIN来合并数据。屏幕快照#4和#5显示了示例包执行和执行持续时间。执行基于合并联接转换的包花费了**05
分钟14
秒719
毫秒。1.第二个包使用了具有完全缓存(默认设置)的
Lookup
转换。屏幕快照#6和#7显示了示例包执行和执行持续时间。执行基于查找转换的包花费了11
分钟03
秒610
毫秒。您可能会遇到警告消息信息:The buffer manager has allocated nnnnn bytes, even though the memory pressure has been detected and repeated attempts to swap buffers have failed.
这里有一个link,讨论如何计算查找缓存大小。在此包执行期间,尽管数据流任务完成得更快,但管道清理花费了大量时间。1.这并不意味着查找转换是不好的。只是它必须被明智地使用。我经常在我的项目中使用它,但我也不会每天处理1000多万行的查找。通常,我的作业处理200万到300万行,因此性能非常好。最多1000万行,两者的表现都一样好。2大多数时候我注意到瓶颈是目标组件而不是转换。3你可以通过拥有多个目标来克服这个问题。4这里**是一个展示多个目标实现的例子。
1.屏幕截图#8显示了所有三个表中的记录计数。屏幕截图#9显示了每个表中的前6个记录。
SQL脚本:
屏幕截图#1:
屏幕截图#2:
屏幕截图#3:
屏幕截图#4:
屏幕截图#5:
屏幕截图#6:
屏幕截图#7:
屏幕截图#8:
屏幕截图#9:
jchrr9hc2#
合并联接旨在生成与SQL中的联接类似的结果。查找组件的工作方式与SQL联接不同。下面是一个示例,其中的结果会有所不同。
如果输入1(例如Invoices)和输入2(例如Invoices Line Items)之间存在一对多关系,则您希望这两个输入的组合结果包括单个发票的一行或多行。
使用合并联接,您将获得所需的输出。使用查找,其中输入2是查找源,输出将是每张发票一行,无论输入2中存在多少行。我不记得数据将来自输入2的哪一行,但我敢肯定您至少会收到重复数据警告。
因此,每个组件在SSIS中都有自己的角色。
qnakjoqk3#
我建议考虑第三种选择。你的OLE DBSource可以包含一个查询而不是一个表,你可以在那里做连接。这不是在所有情况下都好,但是当你可以使用它的时候,你就不必事先排序了。
eeq64g8w4#
查找类似于合并联接组件中的左联接。合并可以执行其他类型的联接,但如果这正是您所需要的,则主要区别在于性能和方便性。
根据要查找的数据量(查找组件的输入)和引用的数据量(查找缓存或查找数据源大小)的相对不同,它们的性能特征可能会有很大的不同。
例如,如果您只需要查找10行,但引用的数据集是1000万行-使用部分缓存或无缓存模式查找会更快,因为它只提取10条记录,而不是1000万。如果您需要查找1000万行,引用的数据集为10行-完全缓存的查找可能更快(除非这1000万行已经排序,您可以尝试合并联接)。如果两个数据集都很大(特别是超过可用RAM时)或较大的数据集已排序,则合并可能是更好的选择。
lymgl2op5#
有两个不同之处:
这导致:如果生成一个排序列表并不费力,并且您想要超过大约1%的行(在流式传输时,单个行选择的成本是同一行成本的~100倍)(您不想在内存中对一个1000万行的表进行排序..),那么合并连接是可行的方法。
如果您只期望少量的匹配项(启用缓存时,查找不同的值),那么查找会更好。
对我来说,这两者之间的权衡在于需要查找的10k和100k行之间。
哪个更快取决于
kd3sttzy6#
合并联接允许您根据一个或多个条件联接到多个列,而查找则有更多的限制,因为它仅根据某些匹配的列信息获取一个或多个值--将对数据源中的每个值运行查找查询(尽管SSIS将在可能的情况下缓存数据源)。
这实际上取决于两个数据源所包含的内容以及您希望最终数据源在合并后如何处理。您能否提供更多有关DTS包中架构的详细信息?
另一个要考虑的因素是性能,如果使用不当,每个都可能比另一个慢,但同样,这取决于您拥有的数据量和数据源模式。
7rtdyuoh7#
我知道这是一个老问题,但我觉得给出的答案没有涵盖的一个关键点是,由于合并联接合并两个数据流,因此它可以合并来自任何源的数据。而使用查找时,必须在OLE DB中保存一个数据源。