SQL Server LEFT OUTER JOIN 查询性能

Posted

技术标签:

【中文标题】SQL Server LEFT OUTER JOIN 查询性能【英文标题】:SQL Server LEFT OUTER JOIN Query Performance 【发布时间】:2017-01-31 15:52:27 【问题描述】:

我遇到了一个奇怪的性能问题。我有一个基于 CTE 的观点。这是我多年前写的一个视图,它一直运行没有问题。突然,在 4 天前,运行 1 到 2 分钟的查询运行了几个小时,然后我们发现了长时间运行的查询并停止了它。

CTE 生成代理执行的事务的时间戳列表。然后我从 CTE 中选择,使用后续事务的时间戳确定代理在每个事务上花费的时间长度。

WITH [CTE_TABLE] (COLUMNS) AS
    (
    SELECT [INDEXED COLUMNS]
         ,[WINDOWED FUNCTION] AS ROWNUM
    FROM [DB_TABLE]
    WHERE [EMPLOYEE_ID] = 111213
    )

    SELECT [T1].[EMPLOYEE_ID]
        ,[T1].[TRANSACTION_NAME]
        ,[T1].[TIMESTAMP]          AS [START_TIME]
        ,[T2].[TIMESTAMP]          AS [END_TIME]
    FROM [CTE_TABLE] [T1]
         LEFT OUTER JOIN [CTE_TABLE] [T2] ON
            (
            [T1].[EMPLOYEE_ID] = [T2].[EMPLOYEE_ID]
            AND [T1].[ROWNUM]  = [T2].[ROWNUM] + 1
            )

在测试中,我过滤特定代理。如果它运行 CTE 的内部部分,它会在不到一秒的时间内生成 500 条记录。 (当不过滤单个代理时,它会在 14 秒内生成 95K 条记录。这是正常的运行时间范围。)如果我使用简单的 SELECT * FROM [CTE_TABLE] 运行 CTE,它也会在不到一秒的时间内运行。当我使用 INNER JOIN 运行它时,它再次运行不到一秒钟。最后,当我将它作为 LEFT OUTER JOIN 运行时,仅针对单个代理的 500 条记录就需要一分半钟。我需要 LEFT OUTER JOIN,因为当天的最终记录是代理注销系统,它永远没有要加入的记录。

我从中提取的表超过 22GB,有 5 亿行。从这个表中选择记录一天需要14秒,或者单个代理不到一秒,所以我认为性能瓶颈不是来自源表。瓶颈发生在 LEFT OUTER JOIN 回到 CTE,但我一直有 LEFT OUTER JOIN。同样,非常奇怪的方面是这仅在 4 天前开始。我检查了服务器上的空间,有很多。 CPU尖峰到大约。 25% 并保持在那里,直到查询结束运行,无论是自行结束,还是由管理员停止。

我希望有人对造成这种情况的原因有一些想法。它似乎是从哪里冒出来的。

【问题讨论】:

您运行的是什么版本的 SQL Server?如果您在 2012 年以上,看起来是使用 LEAD/LAG 的不错选择。 【参考方案1】:

再一次,非常奇怪的是,这只是从 4 天前开始的

我建议更新相关表的统计信息并尝试重建索引

瓶颈出现在 LEFT OUTER JOIN 回 CTE

CTE 不会有任何统计信息,我建议将 CTE 物质化到 Temp 表中,看看这是否有帮助

【讨论】:

重建索引成功了!谢谢!如果可能的话,为什么这会影响 INNER JOIN Vs 的性能?内存中数据表示的左外连接? 更改连接会导致优化器采用不同的扫描或搜索路径,这进一步基于可用的统计信息 @UncleJasper75:也请发布执行计划,继续进行 如果这些数据完全存在于内存中,我看不出任何碎片问题

以上是关于SQL Server LEFT OUTER JOIN 查询性能的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server JOINS:SQL Server 中是不是默认关联“JOIN”语句“LEFT OUTER”? [复制]

SQL Server LEFT OUTER JOIN 查询性能

SQL Server:与 TOP 1 的 LEFT OUTER JOIN 最多选择一行

SQL Server之连接

sql delete_left_outer.sql

Spark SQL 中的 OUTER 和 FULL OUTER 有区别吗?