导致查询变慢的参数

时间:2019-09-19 03:56:51

标签: sql sql-server tsql parameters

我有这个查询

DECLARE @Company VARCHAR(20) = 'ABC'
DECLARE @Train INT = 1

SELECT L.*
FROM vemd_episodes_firstnet_currentPatients L 
INNER JOIN vemd_episodes E ON E.Company = L.Company 
                           AND E.cpid = L.cpid  
                           AND E.dDate = L.dDate
WHERE L.Company = @Company
  AND ((census_datetime NOT IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 1)
       OR (census_datetime IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 0))

这需要永远的时间。

1分钟后,它仅检索400条记录,并且仍在运行。

此查询应获取的记录总数约为500,000条记录。

enter image description here

但是当我对查询中的参数进行硬编码

SELECT L.*
FROM vemd_episodes_firstnet_currentPatients L 
INNER JOIN vemd_episodes E ON E.Company = L.Company 
                           AND E.cpid = L.cpid  
                           AND E.dDate = L.dDate
WHERE L.Company = 'ABC'
  AND ((census_datetime NOT IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND 1 = 1)
       OR (census_datetime IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND 1 = 0))

它非常快,可以在16秒内检索500k记录。

为什么在where子句中使用参数会导致此问题?以及如何解决?

编辑:

我不能一直运行到最后

所以我选择前1000名并制定了执行计划

enter image description here

2 个答案:

答案 0 :(得分:4)

您可以尝试使用重新编译选项OPTION (RECOMPILE)查询 对于参数化查询,SQL有时会选择错误的执行计划并坚持使用它。

DECLARE @Company VARCHAR(20) = 'ABC'
DECLARE @Train INT = 1

SELECT L.*
FROM vemd_episodes_firstnet_currentPatients L 
INNER JOIN vemd_episodes E ON E.Company = L.Company 
                           AND E.cpid = L.cpid  
                           AND E.dDate = L.dDate
WHERE L.Company = @Company
  AND ((census_datetime NOT IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 1)
       OR (census_datetime IN (SELECT MAX(census_datetime) FROM vemd_episodes_firstnet_currentPatients ) AND @Train = 0))
OPTION  (RECOMPILE)

答案 1 :(得分:2)

尝试使用窗口功能:

SELECT L.*
FROM (SELECT L.*,
             MAX(census_datetime) OVER () as max_census_datetime
      FROM vemd_episodes_firstnet_currentPatients L 
     ) L JOIN
     vemd_episodes E
     ON E.Company = L.Company AND
        E.cpid = L.cpid AND
        E.dDate = L.dDate
WHERE L.Company = @Company AND
      ((census_datetime <> max_census_datetime AND @Train = 1) OR
       (census_datetime = max_census_datetime AND @Train = 0)
      );

优化器应该发现使用更简单的where子句可以更容易地生成适当的执行计划。