首页 > 解决方案 > 变量使查询性能变差

问题描述

我有这个查询,当我声明变量时性能会急剧下降:

DECLARE @StartDate DATETIME,
        @EndDate   DATETIME

SET @StartDate = '2018-08-13'
SET @EndDate   = '2018-08-19'

SELECT *
FROM [DIME_WH].[dbo].[FactOrderLines2] FL (nolock)
WHERE DD_OrderDate >= @StartDate
  AND DD_OrderDate <= @EndDate

这比这条 SQL 语句慢得多:

SELECT *
FROM [DIME_WH].[dbo].[FactOrderLines2] FL (nolock)
WHERE DD_OrderDate >= '2018-08-01'
  AND DD_OrderDate <= '2018-08-17'

两个查询最终都将返回相同的结果。

标签: sqlsql-servertsqlsql-server-2016

解决方案


SELECT * FROM [DIME_WH].[dbo].[FactOrderLines2] FL (nolock)
WHERE DD_OrderDate >= '2018-08-01'
  AND DD_OrderDate <= '2018-08-17'

当参数中使用常量时,则为此查询Optimiser创建special plan。因此,如果使用相同的值执行相同的查询,则重用计划,如果值更改,则创建另一个计划。

所以具有恒定值的参数很快。

SELECT *
FROM [DIME_WH].[dbo].[FactOrderLines2] FL (nolock)
WHERE DD_OrderDate >= @StartDate
  AND DD_OrderDate <= @EndDate

在参数中使用变量时,优化器为传递的第一个参数值创建执行计划。

例如 @StartDate='2018-08-01'@EndDate='2018-08-07'第一次通过值。然后优化器创建最佳执行计划。这个计划对于这个价值来说已经足够好了。下一次时间 @StartDate='2018-08-01'@EndDate='2018-08-31' 值通过,然后使用相同的先前计划,这可能不是此参数的最佳选择。

换句话说,对于第一个值是最优的相同计划对于另一个值是次优的。

所以查询可能会执行很差而且很慢。这被称为Parameter sniffing.

有几种方法可以克服这个问题。

参数嗅探

注意:在这个线程中,我们只关注为什么可变性能很慢,而其他因素保持不变。


推荐阅读