【问题标题】:When will SQL Server Choose a Hash Join over a Merge Join?SQL Server 何时会选择散列连接而不是合并连接?
【发布时间】:2015-05-07 09:40:12
【问题描述】:

我有一个大型查询,其中包含许多我正在尝试调整的连接,一个警告信号是整个过程中使用了很多很多哈希连接。我下到查询树的底部,找到了那里的第一个连接,这是一个内部连接。

表 A 正在使用聚集索引扫描来检索其数据,这些数据按连接列排序。 表 B 正在使用非聚集索引扫描,它也按连接列排序。

当我单独连接这两个表并选择同一组列时,优化器使用合并连接。要连接的集合大小大致相同,而且不是很大(

什么可以解释在这种情况下优化器选择散列连接而不是合并连接?

编辑

根据要求,我添加了更多细节。索引定义为:

CREATE NONCLUSTERED INDEX NCL_Asset_Issuer_MergeInduce ON Asset.IssuerCompanyId (CompanyId)INCLUDE (IsPrivate,HasPublicEquity,Ticker,FinancialTemplateID,BondTicker,SICOther1ID,SICOther4ID,SICSandPID,SICOther3ID,SICMoodyID,CurrencyTypeID,SecondaryAnalystID,AnalystID,SICOshaID,SecondaryBondTicker,FiscalYearEnd,EquityExchangeID);

CREATE NONCLUSTERED INDEX NCL_Asset_IssuerCustom_IssuerId ON Asset.IssuerCustom (IssuerID) INCLUDE (Text3,ListItem1ID,ListItem5ID,ListItem3ID,ListItem2ID,Version,text4,TextLong15,ListItem6ID)

正如我之前提到的,以下查询将返回一个合并连接:

SELECT IsPrivate,HasPublicEquity,Ticker,FinancialTemplateID,BondTicker,SICOther1ID,SICOther4ID,SICSandPID,SICOther3ID,SICMoodyID,CurrencyTypeID,SecondaryAnalystID,AnalystID,SICOshaID,SecondaryBondTicker,FiscalYearEnd,EquityExchangeID,ic.ListItem2Id,ic.ListItem3ID,ic.IssuerId
FROM Asset.Issuer i
INNER JOIN Asset.IssuerCustom ic ON i.CompanyId = ic.IssuerId;

如您所见,查询同时使用了上述两个索引。另一方面,同样的连接出现在一个更大的查询中,下图显示了计划的一角,这个连接作为哈希连接发生:

我可以看到的一个区别是,在哪个表是“内部”表与哪个是“外部”表方面存在逆转。不过,如果两个查询都是同一列上的内部联接,为什么这会影响执行计划?

【问题讨论】:

  • 是否可以通过包含所需的 INCLUDE 列来使非聚集索引成为“覆盖”索引以满足查询的 SELECT/WHERE/ORDER BY 要求?被连接的两个表的行数是否大致相同?您确定在“大型”查询中,您指定的索引在您看到散列连接的所有情况下都被使用?
  • A merge join 只有在两个输入都已经排序时才可能 - 否则,将选择其他一些连接(通常是哈希连接)
  • 我从未见过在适用的情况下不使用合并连接的情况。它每行更便宜,启动成本更低,因此如果适用,它总是更优越。发布表定义和实际执行计划。我们肯定会找到合并连接不适用的原因。
  • 我添加了更多细节。大型查询太大而无法分析,但索引和行数如上所示。我指出的一件事是表格的左/右方向发生了变化,但都是内连接,所以应该没关系。
  • 统计数据也会影响加入选择。某些连接只有在您有大量记录时才会更有效,因此它将使用估计的记录数来做出选择。

标签: sql-server hash merge


【解决方案1】:

SQL Server 查询优化器不保证最佳查询。它会在自己设置的时间内寻找最佳查询。随着查询变大,使用多个连接,不同组合的数量呈指数级增长,因此不可能探索每条可能的路径并因此保证最佳解决方案。

通常,如果您的表设计合理(具有适当的索引)并且统计信息是最新的,您应该能够相信查询优化器会做得很好。

不同的连接选择可能是由于可用的资源不同 -(CPU 和内存)考虑到并行执行的计划的其他部分。

如果您想进一步调查,我会使用连接提示测试运行,以确定执行计划是否做出了最佳决策。也可能值得使用查询提示 MAXDOP=1 进行测试,以确定并行执行是否会影响优化器所做的选择。

【讨论】:

    猜你喜欢
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多