【发布时间】: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