优化器似乎对 varchar 参数的可空性感到困惑,我不确定我是否理解原因。我正在使用 SQL Server 2008 顺便说一句。所有被查询的列都被索引。TDate 列是一个聚集的分区索引。FooValue 列是索引的、不可为空的列。
例子:
CREATE PROCEDURE dbo.MyExample_sp @SDate DATETIME, @EDate DATETIME, @FooValue VARCHAR(50)
AS
SET NOCOUNT ON
--To avoid parameter spoofing / sniffing
DECLARE @sDate1 DATETIME, @eDate1 DATETIME
SET @sDate1 = @sDate
SET @eDate1 = @eDate
SELECT
fd.Col1,
fd.Col2,
fd.TDate,
fl.FooValue,
fd.AccountNum
FROM dbo.FooData fd
INNER JOIN dbo.FooLookup fl
ON fl.FL_ID = fd.FL_ID
WHERE fd.TDate >= @sDate1
AND fd.TDate < @eDate1
AND fl.FooValue = @FooValue
将其作为查询运行按预期工作。所有索引都是搜索,没有欺骗等。通过执行 sproc 运行它需要 20 倍的时间 - 相同的查询 - 相同的参数。但是,如果我进行以下更改(最后一行),一切都会再次运行。
CREATE PROCEDURE dbo.MyExample_sp @SDate DATETIME, @EDate DATETIME, @FooValue VARCHAR(50)
AS
SET NOCOUNT ON
--To avoid parameter spoofing / sniffing
DECLARE @sDate1, @eDate1
SET @sDate1 = @sDate
SET @eDate1 = @eDate
SELECT
fd.Col1,
fd.Col2,
fd.TDate,
fl.FooValue,
fd.AccountNum
FROM dbo.FooData fd
INNER JOIN dbo.FooLookup fl
ON fl.FL_ID = fd.FL_ID
WHERE fd.TDate >= @sDate1
AND fd.TDate < @eDate1
AND fl.FooValue = ISNULL(@FooValue, 'testthis')
就像优化器对参数是否可以为空感到困惑?此外,向参数添加默认值没有任何区别。除非我使用 = isnull(@parameter, 'some constant'),否则 sproc 仍然需要永远运行
我很高兴我明白了这一点。但是,我想了解为什么会发生这种情况,以及是否有更优雅的方法来解决这个问题。