【问题标题】:Slow performing T-SQL query with two joins to the same table使用两个连接到同一个表的慢速执行 T-SQL 查询
【发布时间】:2020-06-29 03:35:29
【问题描述】:

我正在努力弄清楚下面显示的 T-SQL 查询发生了什么。

您将看到同一个表的两个内部连接,尽管连接条件不同。第一个连接本身运行大约 21 秒,如果我自己运行第二个连接,它会在大约 27 秒内完成。

如果我将两个连接都保留在原位,则查询会运行并运行,直到我最终停止查询。适当的索引似乎已经到位,我知道这个查询在不同的环境中运行,马力较小,唯一的区别是另一台服务器运行的是 SQL Server 2012,而我运行的是 SQL Server 2016,尽管数据库处于 2012 兼容模式:

此连接运行约 21 秒。

SELECT
    COUNT(*)
FROM 
    dbo.SPONSORSHIP as s
INNER JOIN 
    dbo.SPONSORSHIPTRANSACTION AS st 
        ON st.SPONSORSHIPCOMMITMENTID = s.SPONSORSHIPCOMMITMENTID
        AND st.TRANSACTIONSEQUENCE = (SELECT MIN(TRANSACTIONSEQUENCE)
                                      FROM dbo.SPONSORSHIPTRANSACTION AS ms
                                      WHERE ms.SPONSORSHIPCOMMITMENTID = s.SPONSORSHIPCOMMITMENTID
                                        AND ms.TARGETSPONSORSHIPID = s.ID)

此连接运行约 27 秒。

SELECT
    COUNT(*) 
FROM
    dbo.SPONSORSHIP AS s
INNER JOIN 
    dbo.SPONSORSHIPTRANSACTION AS lt ON lt.SPONSORSHIPCOMMITMENTID = s.SPONSORSHIPCOMMITMENTID 
        AND lt.TRANSACTIONSEQUENCE = (SELECT MAX(TRANSACTIONSEQUENCE) 
                                      FROM dbo.SPONSORSHIPTRANSACTION AS ms 
                                      WHERE ms.SPONSORSHIPCOMMITMENTID = s.SPONSORSHIPCOMMITMENTID 
                                        AND s.ID IN (ms.CONTEXTSPONSORSHIPID, 
                                                     ms.TARGETSPONSORSHIPID, 
                                                     ms.DECLINEDSPONSORSHIPID) 
                                        AND ms.ACTIONCODE <> 9)

【问题讨论】:

    标签: sql-server performance tsql indexing inner-join


    【解决方案1】:

    这些都被认为是correlated subqueries。您通常应该避免这种模式,因为它会导致所谓的“RBAR”......这是“Row by Agonizing Row”。在您专注于解决此特定查询之前,我建议您重新访问查询本身,看看您是否可以通过更基于集合的方法解决此问题。您会发现,在大多数情况下,您还有其他方法可以实现这一目标并显着降低成本。

    举个例子:

    select
        total_count
        ,row_sequence
    from 
        ( 
        SELECT
        total_count = COUNT(*)
        ,row_sequence = row_number() over(order by st.TRANSACTIONSEQUENCE asc)
        FROM 
            dbo.SPONSORSHIP as s
        INNER JOIN dbo.SPONSORSHIPTRANSACTION AS st
        ON st.SPONSORSHIPCOMMITMENTID = s.SPONSORSHIPCOMMITMENTID
    ) as x
    where
        x.row_sequence = 1
    
    

    这是一个未经测试的简单示例。为了将来参考,如果您想要最佳答案,最好生成一个可以使用的临时表或测试数据集,以便有人可以提供完整的工作示例。

    我给出的示例显示了所谓的windowing function。当您看到单词序列、需要组中的第一个/最后一个等等时,请仔细查看它们以帮助选择结果。

    希望这能给你一些想法!欢迎来到堆栈溢出! ?

    【讨论】:

    • 谢谢谢尔顿!不幸的是,这是来自第三方产品的代码生成查询,尽管我很想重写查询,但我必须回到他们那里并报告这个问题。感谢您的及时回复!
    • 哦...修改供应商查询代码总是很有趣?
    猜你喜欢
    • 2011-06-16
    • 1970-01-01
    • 2016-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多