SQL Server SSIS中的合并联接转换和查找转换之间有什么区别?

9avjhtql  于 2022-12-26  发布在  其他
关注(0)|答案(7)|浏览(307)

大家好,我是SSIS包的新手,在编写一个包的同时还在阅读有关它们的内容。
我需要将DTS转换为SSIS包,并且需要对来自不同数据库的两个源执行连接,我想知道使用查找还是合并连接哪个方法更好?
从表面上看,它们似乎非常相似。“合并联接”要求事先对数据进行排序,而“查找”不要求这样做。任何建议都将非常有用。谢谢。

xzabzqsa

xzabzqsa1#

屏幕截图#1显示了Merge Join transformationLookup transformation之间的几个区别点。

关于查找:

如果您想根据源1的输入在源2中查找匹配的行,并且您知道每个输入行只有一个匹配,那么我建议使用查找操作。例如,您的OrderDetails表,并且您想查找匹配的Order IdCustomer Number,那么查找是一个更好的选择。

关于合并联接:

如果要执行连接,例如从Address表中为Customer表中的给定客户提取所有地址(Home、Work、Other),则必须使用Merge Join,因为客户可以有一个或多个地址与之关联。

比较示例:

下面的场景演示了Merge JoinLookup之间的性能差异。这里使用的数据是一对一联接,这是它们之间唯一可以比较的共同场景。
1.我有三个名为dbo.ItemPriceInfodbo.ItemDiscountInfodbo.ItemAmount的表。SQL脚本部分提供了这些表的创建脚本。
1.表dbo.ItemPriceInfodbo.ItemDiscountInfo都有13,349,729行。这两个表都将ItemNumber作为公用列。ItemPriceInfo包含价格信息,ItemDiscountInfo包含折扣信息。屏幕快照#2显示了每个表中的行数。屏幕快照#3显示了前6行,以给予表中存在的数据。
1.我创建了两个SSIS包来比较合并联接转换和查找转换的性能。这两个包都必须从表dbo.ItemPriceInfodbo.ItemDiscountInfo获取信息,计算总量并将其保存到表dbo.ItemAmount
1.第一个包使用了Merge Join转换,并在该转换内部使用INNER JOIN来合并数据。屏幕快照#4和#5显示了示例包执行和执行持续时间。执行基于合并联接转换的包花费了**05分钟14719毫秒。
1.第二个包使用了具有完全缓存(默认设置)的Lookup转换。屏幕快照#6和#7显示了示例包执行和执行持续时间。执行基于查找转换的包花费了
11分钟03610毫秒。您可能会遇到警告消息信息: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

屏幕截图#1:

屏幕截图#2:

屏幕截图#3:

屏幕截图#4:

屏幕截图#5:

屏幕截图#6:

屏幕截图#7:

屏幕截图#8:

屏幕截图#9:

jchrr9hc

jchrr9hc2#

合并联接旨在生成与SQL中的联接类似的结果。查找组件的工作方式与SQL联接不同。下面是一个示例,其中的结果会有所不同。
如果输入1(例如Invoices)和输入2(例如Invoices Line Items)之间存在一对多关系,则您希望这两个输入的组合结果包括单个发票的一行或多行。
使用合并联接,您将获得所需的输出。使用查找,其中输入2是查找源,输出将是每张发票一行,无论输入2中存在多少行。我不记得数据将来自输入2的哪一行,但我敢肯定您至少会收到重复数据警告。
因此,每个组件在SSIS中都有自己的角色。

qnakjoqk

qnakjoqk3#

我建议考虑第三种选择。你的OLE DBSource可以包含一个查询而不是一个表,你可以在那里做连接。这不是在所有情况下都好,但是当你可以使用它的时候,你就不必事先排序了。

eeq64g8w

eeq64g8w4#

查找类似于合并联接组件中的左联接。合并可以执行其他类型的联接,但如果这正是您所需要的,则主要区别在于性能和方便性。
根据要查找的数据量(查找组件的输入)和引用的数据量(查找缓存或查找数据源大小)的相对不同,它们的性能特征可能会有很大的不同。
例如,如果您只需要查找10行,但引用的数据集是1000万行-使用部分缓存或无缓存模式查找会更快,因为它只提取10条记录,而不是1000万。如果您需要查找1000万行,引用的数据集为10行-完全缓存的查找可能更快(除非这1000万行已经排序,您可以尝试合并联接)。如果两个数据集都很大(特别是超过可用RAM时)或较大的数据集已排序,则合并可能是更好的选择。

lymgl2op

lymgl2op5#

有两个不同之处:

  • 排序:
  • 合并联接要求 * 两个 * 输入以相同的方式排序
  • 查找不需要对任一输入进行排序。
  • 数据库查询负载:
  • 合并联接不引用数据库,而只引用2个输入流(尽管引用数据通常采用'select * from table order by join critera'的形式)
  • lookup将为请求连接的每个值(不同的,如果缓存)发出一个查询。这很快就会比上面的select开销更大。

这导致:如果生成一个排序列表并不费力,并且您想要超过大约1%的行(在流式传输时,单个行选择的成本是同一行成本的~100倍)(您不想在内存中对一个1000万行的表进行排序..),那么合并连接是可行的方法。
如果您只期望少量的匹配项(启用缓存时,查找不同的值),那么查找会更好。
对我来说,这两者之间的权衡在于需要查找的10k和100k行之间。
哪个更快取决于

  • 要处理的行的总数。(如果表是内存驻留的,则合并它的数据排序是便宜的)
  • 预期的重复查找数。(查找的每行开销高)
  • 如果可以选择排序数据(注意,文本排序受代码排序规则影响,因此要注意sql认为排序的内容也是ssis认为排序的内容)
  • 你将查找整个表格的百分比。(合并将需要选择每一行,如果你在一边只有几行,查找会更好)
  • 行的宽度(每页的行可以强烈地影响进行单次查找与扫描的IO成本)(窄行-〉更优选合并)
  • 磁盘上数据的顺序(易于生成排序输出,首选合并,如果可以按物理磁盘顺序组织查找,由于缓存未命中较少,查找成本较低)
  • ssis服务器和目标之间的网络延迟(延迟较大-〉首选合并)
  • 你希望花费多少编码工作(merge编写起来有点复杂)
  • 输入数据的排序--SSIS merge对于包含非字母数字字符但不是nvarchar的文本字符串的排序有着很好的想法。(这涉及到排序,让sql发出一个ssis乐于合并的排序是很困难的)
kd3sttzy

kd3sttzy6#

合并联接允许您根据一个或多个条件联接到多个列,而查找则有更多的限制,因为它仅根据某些匹配的列信息获取一个或多个值--将对数据源中的每个值运行查找查询(尽管SSIS将在可能的情况下缓存数据源)。
这实际上取决于两个数据源所包含的内容以及您希望最终数据源在合并后如何处理。您能否提供更多有关DTS包中架构的详细信息?
另一个要考虑的因素是性能,如果使用不当,每个都可能比另一个慢,但同样,这取决于您拥有的数据量和数据源模式。

7rtdyuoh

7rtdyuoh7#

我知道这是一个老问题,但我觉得给出的答案没有涵盖的一个关键点是,由于合并联接合并两个数据流,因此它可以合并来自任何源的数据。而使用查找时,必须在OLE DB中保存一个数据源。

相关问题