Sql server 具有相同外键的左联接表:哈希键探测占50%

Sql server 具有相同外键的左联接表:哈希键探测占50%,sql-server,hash,left-join,sql-execution-plan,Sql Server,Hash,Left Join,Sql Execution Plan,我们有3张桌子: 表0,包含ID(=主键) 表1中包含表0中ID的可为空FK 表2包含表0中ID的可为空FK 我们的查询运行速度太慢,即使索引正确。在查看执行计划(SQL Server 2014)时,他在左侧外部连接上浪费了大量时间。SQL server使用“哈希匹配”,使其成为一个内部联接,成本为47%(如果我没有在where子句中显式设置[FI].[pId]=[FPF].[pId],则成本为50%) 解释说他对[FI].[pId]使用了一个“散列键探测” SELECT [FI].[ID

我们有3张桌子:

  • 表0,包含ID(=主键)
  • 表1中包含表0中ID的可为空FK
  • 表2包含表0中ID的可为空FK
我们的查询运行速度太慢,即使索引正确。在查看执行计划(SQL Server 2014)时,他在左侧外部连接上浪费了大量时间。SQL server使用“哈希匹配”,使其成为一个内部联接,成本为47%(如果我没有在where子句中显式设置
[FI].[pId]=[FPF].[pId]
,则成本为50%)

解释说他对[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与主键链接起来,但是没有任何区别。同样,使用外部应用也会得到相同的结果。我也一直在两张表上使用索引,但没有任何利润


有没有人可以分享一些关于我在这里可能做错了什么的想法?

尽量减少在左侧连接上返回的记录数

您只对[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]
在[表2]中,使用以下索引:

CREATE NONCLUSTERED INDEX idx ON [Table2](pID) INCLUDE (tId,Name)
额外的代码可以将查询转换为内部联接。那会更快

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

您真的需要按订购吗?如果没有,则将其删除。

通过在建议的索引中添加数据来解决,并将其添加到pid之前。
由于实际行数和估计行数之间的巨大差异,显示统计数据的执行计划已过时,但内部联接使情况变得更糟。因此,请使用“更新统计信息”或sp_updatestats更新表的统计信息。嗨,buddi,谢谢你的提示。我只是这么做了,但结果是sameOR往往是罪魁祸首,试试Union吧。谢谢你的提示。它会导致最终的结果。