为什么我的查询要使用变量而不是文字来挂起/运行?

时间:2017-12-05 20:28:17

标签: sql-server tsql

我有一个相对简单的查询,当我在where子句中使用文字值运行它时,运行大约2.5分钟。但是当我使用包含相同值的局部变量运行它时,查询会挂起或大概永远运行。 (我还没试过让它运行超过90分钟。)

这里是名称混淆的查询(因为规则)。我尝试用INNER JOIN替换EXISTS,但它没有帮助。下面的变量是局部变量,而不是参数。这不是一个参数嗅探问题。但是当变量用它们的文字值(两个DATETIME和三个INT)替换时,查询运行正常。

DECLARE @SubsetStart DATETIME = '2013-01-01 00:00:00'
DECLARE @SubsetEnd DATETIME = '2013-12-31 23:59:59'
DECLARE @SCD INT = 217
DECLARE @MFP INT = 8
DECLARE @EXP INT = 39298

SELECT
    MainTable.MFID ManufacturerID
    ,SUM(MainTable.AMT) AMT
FROM
    MainTable
WHERE
    EXISTS (
        SELECT TID
        FROM MTMTable 
        WHERE MTMTable.TID = MainTable.TID
            AND MTMTable.DEL = 0
            AND EXISTS (
                SELECT CID
                FROM RelatedTable
                WHERE RelatedTable.CID = MTMTable.CID
                    AND DEL = 0
                    AND RelatedTable.TD BETWEEN '2013-01-1' AND '2013-12-31 23:59:59'
            )
    )
    AND EXISTS (
        SELECT AID 
        FROM OtherTable 
        WHERE OtherTable.AID = MainTable.CAID
            AND OtherTable.AHTID = 8
            AND OtherTable.DEL = 0)
    AND MainTable.DAID <> 39298
    AND MainTable.SID = 217
GROUP BY
    MainTable.MFID

我完全不知道为什么这个简单的查询应该以这种方式运行。

1 个答案:

答案 0 :(得分:0)

问题在于,当您使用局部变量时,优化器会忽略它们的值并使用一般统计假设。基本上在编译时它不知道那些变量的值。您可以使用查询中的OPTION(RECOMPILE)提示来验证这一点,这将使用变量中的值重新编译查询。

您可以阅读有关在存储过程中使用局部变量可能会影响性能的原因:

https://www.brentozar.com/archive/2014/06/tuning-stored-procedures-local-variables-problems/

在这里:

http://www.sqlbadpractices.com/using-local-variables-in-t-sql-queries/