SSIS中的Merge Join和Lookup转换有什么区别?

时间:2011-07-18 15:57:10

标签: sql-server ssis

您好我是SSIS包的新手,并且编写了一个包并同时阅读它们。

我需要将DTS转换为SSIS包,我需要在来自不同数据库的两个源上执行连接,并且想知道什么是更好的apporach,使用查找或合并连接?

表面看起来非常相似。 “合并连接”要求数据先进行排序,而“查找”则不需要这样。任何建议都会非常有帮助。谢谢。

7 个答案:

答案 0 :(得分:79)

屏幕截图# 1 显示几点,以区分Merge Join transformationLookup transformation

关于查询:

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

关于合并加入:

如果要执行联接,例如从Address表中为Customer表中的给定客户提取所有地址(主页,工作,其他),那么您必须使用合并加入,因为客户可以拥有一个或多个与之关联的地址。

要比较的示例:

以下是展示Merge JoinLookup之间性能差异的方案。这里使用的数据是一对一连接,这是它们之间唯一需要比较的方案。

  1. 我有三个名为dbo.ItemPriceInfodbo.ItemDiscountInfodbo.ItemAmount的表格。 SQL脚本部分提供了为这些表创建脚本。

  2. dbo.ItemPriceInfodbo.ItemDiscountInfo都有13,349,729行。两个表都将ItemNumber作为公共列。 ItemPriceInfo具有价格信息,ItemDiscountInfo具有折扣信息。屏幕截图# 2 显示每个表中的行数。屏幕截图# 3 显示前6行,以便了解表格中的数据。

  3. 我创建了两个SSIS包来比较Merge Join和Lookup转换的性能。这两个包都必须从表dbo.ItemPriceInfodbo.ItemDiscountInfo获取信息,计算总金额并将其保存到表dbo.ItemAmount

  4. 第一个包使用Merge Join转换,内部使用INNER JOIN来组合数据。屏幕截图# 4 和# 5 显示示例包执行和执行持续时间。 05 分钟 14 719 毫秒执行基于合并连接转换的程序包。

  5. 第二个包使用Lookup转换为完全缓存(这是默认设置)。 creenshots# 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,其中讨论了如何计算查找缓存大小。在此程序包执行期间,即使数据流任务完成得更快,管道清理也需要花费大量时间。

  6. 意味着查找转换很糟糕。它只是必须明智地使用它。我经常在我的项目中使用它,但是我每天都不会处理超过10万行的查询。通常,我的作业处理2到3百万行,为此表现非常好。多达1000万行,两者表现同样出色。大多数时候我注意到的是瓶颈原来是目标组件而不是转换。您可以通过拥有多个目的地来克服这一点Here是一个显示多个目的地实现的示例。

  7. 屏幕截图# 8 显示所有三个表中的记录计数。屏幕截图# 9 显示每个表格中的前6条记录。

  8. 希望有所帮助。

    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:

    1

    屏幕截图#2:

    2

    屏幕截图#3:

    3

    屏幕截图#4:

    4

    屏幕截图#5:

    5

    屏幕截图#6:

    6

    屏幕截图#7:

    7

    屏幕截图#8:

    8

    屏幕截图#9:

    9

答案 1 :(得分:9)

Merge Join旨在生成类似于JOIN在SQL中的工作方式的结果。 Lookup组件不像SQL JOIN那样工作。以下是结果不同的示例。

如果您在输入1(例如,发票)和输入2(例如,发票行项目)之间存在一对多关系,则您希望这两个输入的组合结果包含一行或多行单一发票。

使用合并加入,您将获得所需的输出。使用Lookup,其中输入2是查找源,输出将是每个发票一行,无论输入2中存在多少行。我不记得输入2中哪一行数据会来,但我'我相信你至少会收到重复数据警告。

因此,每个组件在SSIS中都有自己的作用。

答案 2 :(得分:4)

我建议考虑第三种方案。您的OLE DBSource可以包含查询而不是表,您可以在那里进行连接。这在所有情况下都不好,但是当你可以使用它时,你不必事先排序。

答案 3 :(得分:2)

Lookup类似于Merge Join组件中的left-join。合并可以执行其他类型的连接,但如果这是您想要的,则差异主要在于性能和便利性。

它们的性能特征可能会有很大差异,具体取决于要查找的数据的相对数量(输入到查找组件)和引用数据的数量(查找缓存或查找数据源大小)。

E.g。如果您只需要查找10行,但引用的数据集是1000万行 - 使用部分缓存或无缓存模式查找将更快,因为它只能获取10条记录,而不是10万条。如果你需要查找1000万行,并且引用的数据集是10行 - 完全缓存的Lookup可能更快(除非那些1000万行已经分类,你可以尝试Merge Join)。如果两个数据集都很大(特别是如果超过可用RAM)或者较大的数据集已经排序 - 合并可能是更好的选择。

答案 4 :(得分:2)

有两点不同:

  1. 排序:

    • 合并连接要求两个输入以相同的方式排序
    • 查询不需要对任何输入进行排序。
  2. 数据库查询加载:

    • 合并连接不是指数据库,只是指2个输入流(尽管参考数据通常采用' select * from table order by join critera')
    • lookup将为要求加入的每个(不同的,如果缓存的)值发出1个查询。这比上面的选择快得多。
  3. 这会导致: 如果没有努力产生一个排序列表,并且你想要超过大约1%的行(单行选择大约是流式传输时同一行的成本的100倍)(你不想排序10内存中的百万行表..)然后合并连接是要走的路。

    如果您只期望少量匹配(查找不同的值,启用缓存时),则查找更好。

    对我来说,两者之间的权衡需要在10k到10万行之间进行权衡。

    更快的将取决于

    • 要处理的总行数。 (如果表是内存驻留,一种合并它的数据很便宜)
    • 预期的重复查找次数。 (每行查询开销很高)
    • 如果你可以选择排序数据(注意,文本排序受代码排序的影响,所以要小心sql认为排序的也是ssis认为排序的)
    • 您将查找整个表格的百分比。 (合并将要求选择每一行,如果一侧只有几行,查找会更好)
    • 行的宽度(每页行数可以强烈影响单次查找与扫描的io成本)(窄行 - >更多合并首选项)
    • 磁盘上的数据顺序(易于生成排序输出,更喜欢合并,如果您可以按物理磁盘顺序组织查找,由于缓存丢失较少,查找成本较低)
    • ssis服务器与目标之间的网络延迟(较大延迟 - >更喜欢合并)
    • 您希望花费多少编码工作(编写合并要复杂一点)
    • 输入数据的整理 - SSIS合并有关排序包含非字母数字字符但不是nvarchar的文本字符串的奇怪想法。 (这是排序,并让sql发出一个ssis很乐意合并的排序很难)

答案 5 :(得分:1)

Merge Join允许您根据一个或多个条件连接到多个列,而Lookup更受限制,因为它只根据一些匹配的列信息获取一个或多个值 - 查询查询将是运行数据源中的每个值(尽管SSIS会缓存数据源)。

这实际上取决于您的两个数据源包含的内容以及您希望最终源在合并后的外观。您能否提供有关DTS包中模式的更多详细信息?

要考虑的另一件事是表现。如果使用不正确,每个都可能比另一个慢,但同样,它将取决于您拥有的数据量和数据源模式。

答案 6 :(得分:1)

我知道这是一个老问题,但我认为答案中没有涉及的一个关键点是,因为合并连接正在合并两个数据流,所以它可以组合来自任何源的数据。而对于查找,一个数据源必须保存在OLE DB中。