【问题标题】:left join tables which have same foreign key: hash key probe takes 50%具有相同外键的左连接表:哈希键探测占 50%
【发布时间】:2017-05-09 19:11:32
【问题描述】:

我们有 3 张桌子:

  • Table0,包含 ID(= 主键)
  • Table1,其中包含指向 table0 的 ID 的可为空的 FK
  • Table2,其中包含指向 table0 的 ID 的可为空的 FK

我们的查询运行速度太慢,即使它已正确编入索引。在查看执行计划(SQL Server 2014)时,他在左外连接上浪费了很多时间。 SQL 服务器改用“哈希匹配”,使其成为成本 47% 的内部联接(如果我没有在 where 子句中明确设置 [FI].[pId] = [FPF].[PId],则成本为 50%)。

execution plan

解释说他对 [FI].[pId] 使用“散列密钥探测”。

SELECT [FI].[ID], [FI].[Name], [FI].[Data]
FROM [dbo].[Table1] AS [FI] WITH (NOLOCK)
LEFT JOIN [Table2] AS [FPF] WITH (NOLOCK) ON [FI].[pId] = [FPF].[pId]
WHERE
[FI].[pId] = [FPF].[PId] AND -- If I add this explicitly, the query is already a lot faster
(
(
    [FI].[tId] = @tID --is bigint (FK)
    AND
    [Fi].[Name] = @Name --is varchar
)
OR
(
    [FI].[fiType] = 1
)
OR
(
    [FPF].[tId] = @tID
    AND
    [FPF].[Name] = @Name
))
ORDER BY [Fi].[Data]

我什至也尝试将 table0 与主键链接,但这没有任何区别。也使用外部应用给出相同的结果。我也在这两个表上玩过索引,但没有任何利润。

有人可以就我在这里可能做错的事情分享一些想法吗?

【问题讨论】:

  • 显示统计数据的执行计划已经过时,因为实际行数和估计行数之间存在巨大差异。因此,请使用“update statistics”或 sp_updatestats 更新表的统计信息。
  • 您好,伙计,谢谢您的提示。我只是这样做了,但结果是一样的
  • OR 往往是罪魁祸首,试试 Union。

标签: sql-server hash left-join sql-execution-plan


【解决方案1】:

尽量减少可能在左连接上返回的记录数。

您只对 [Table2] 中具有特定 @name 和 @tID 的记录感兴趣,因此请在连接点限制 [Table2] 结果集的大小。

SELECT [FI].[ID], [FI].[Name], [FI].[Data]
FROM [dbo].[Table1] AS [FI] WITH (NOLOCK)
LEFT JOIN [Table2] AS [FPF] WITH (NOLOCK) ON [FI].[pId] = [FPF].[pId]
                                            AND [FPF].[tId] = @tID
                                            AND [FPF].[Name] = @Name
WHERE
[FI].[pId] = [FPF].[PId] AND -- If I add this explicitly, the query is already a lot faster
(
(
    [FI].[tId] = @tID --is bigint (FK)
    AND
    [Fi].[Name] = @Name --is varchar
)
OR
(
    [FI].[fiType] = 1
)
OR
(
    [FPF].[tId] = @tID
    AND
    [FPF].[Name] = @Name
))
ORDER BY [Fi].[Data]

在 [Table2] 上使用这个索引:

CREATE NONCLUSTERED INDEX idx ON [Table2](pID) INCLUDE (tId,Name)

您的额外代码可以将您的查询转换为 INNER JOIN。哪个会更快。

[FI].[pId] = [FPF].[PId] AND -- If I add this explicitly, the query is already a lot faster

您真的需要ORDER BY 吗?如果没有,那就摆脱它。

【讨论】:

  • 感谢您的提示。它导致了最终结果。
【解决方案2】:

通过在建议的索引中添加数据来解决,并将其添加到pid之前。 内部连接让它变得更糟了

【讨论】:

    猜你喜欢
    • 2014-11-21
    • 2019-05-16
    • 2019-05-03
    • 2017-07-13
    • 1970-01-01
    • 2020-11-26
    • 2018-11-13
    • 2011-10-04
    • 2018-02-12
    相关资源
    最近更新 更多