Performance 有人能解释一下这两个问题之间的区别吗?

Performance 有人能解释一下这两个问题之间的区别吗?,performance,sql-server-2008,dateadd,Performance,Sql Server 2008,Dateadd,第一个查询是: declare @myDate datetime = DATEADD(D,-2000,getdate()) SELECT * FROM [myTable] where CreatedDate >= @myDate SELECT * FROM [myTable] where CreatedDate >= DATEADD(D,-2000,getdate()) 第二个问题是: declare @myDate datetime = DATEADD(D,-2000,

第一个查询是:

declare @myDate datetime = DATEADD(D,-2000,getdate())
SELECT * FROM [myTable]  
where CreatedDate >= @myDate
SELECT * FROM [myTable]  
where CreatedDate >= DATEADD(D,-2000,getdate())
第二个问题是:

declare @myDate datetime = DATEADD(D,-2000,getdate())
SELECT * FROM [myTable]  
where CreatedDate >= @myDate
SELECT * FROM [myTable]  
where CreatedDate >= DATEADD(D,-2000,getdate())

我预计第一次查询可能会更快,因为“dateadd”函数只计算一次。但实际上,这两个查询都是2秒,30000行

SQL不会为每一行重新计算DATEADD。无论哪种方式,它都会计算一次,然后在表的各行中与结果进行比较。两种不同的方法,一种可能不必要地比另一种更详细,但最终它们给出相同的结果。

SQL不会为每一行重新计算DATEADD。无论哪种方式,它都会计算一次,然后在表的各行中与结果进行比较。两种不同的方法,一种可能不必要地比另一种更详细,但最终它们给出相同的结果。

SQL server优化器正在帮助使后一种查询更优化


请查看。

SQL server优化器正在帮助使后一个查询更加优化

请查看。

getdate是一个函数,每个函数引用只计算一次,这就是为什么

SELECT GETDATE()
FROM SomeBigTable
无论查询运行多长时间,都将为所有行返回相同的结果

然而,两者之间存在差异。由于第一个使用变量,并且在将变量分配给SQL Server之前编译了计划,因此在没有重新编译的情况下,将假定返回30%的行。此猜测可能导致它使用与第二个查询不同的计划

在过滤器中直接使用GETDATE需要注意的是,它在编译时计算GETDATE,然后选择性可能会发生显著变化,而无需更改查询或数据来触发重新编译。在下面针对1000行表的示例中,使用变量的查询将导致一个计划,该计划估计有300行和一个完整的表扫描,而使用函数调用embedded的查询估计有1行,并执行书签查找。这在第一次运行时是准确的,但在第二次运行时,由于时间的推移,现在所有行都符合条件,它最终会执行1000次这样的随机查找

USE tempdb;

CREATE TABLE [myTable]
(
CreatedDate datetime,
Filler char(8000) NULL
)

CREATE NONCLUSTERED INDEX ix ON [myTable](CreatedDate)

INSERT INTO [myTable](CreatedDate)
/*Insert 1 row that initially qualifies*/
SELECT DATEADD(D,-2001,getdate())
UNION ALL
/*And 999 rows that don't initially qualify*/
SELECT TOP 999 DATEADD(minute,1, DATEADD(D,-2000,getdate()))
FROM master..spt_values

EXEC('
DECLARE @myDate DATETIME = DATEADD(D,-2000,getdate())
SELECT * 
FROM [myTable]  
WHERE CreatedDate <= @myDate
')

EXEC('
SELECT * 
FROM [myTable]  
WHERE CreatedDate <= DATEADD(D,-2000,getdate())
')

RAISERROR ('Delay',0,1) WITH NOWAIT

WAITFOR DELAY '00:01:01'

EXEC('
DECLARE @myDate DATETIME = DATEADD(D,-2000,getdate())
SELECT * 
FROM [myTable]  
WHERE CreatedDate <= @myDate
')

EXEC('
SELECT * 
FROM [myTable]  
WHERE CreatedDate <= DATEADD(D,-2000,getdate())
')

DROP TABLE [myTable]
getdate是一个函数,每个函数引用只计算一次,这就是为什么

SELECT GETDATE()
FROM SomeBigTable
无论查询运行多长时间,都将为所有行返回相同的结果

然而,两者之间存在差异。由于第一个使用变量,并且在将变量分配给SQL Server之前编译了计划,因此在没有重新编译的情况下,将假定返回30%的行。此猜测可能导致它使用与第二个查询不同的计划

在过滤器中直接使用GETDATE需要注意的是,它在编译时计算GETDATE,然后选择性可能会发生显著变化,而无需更改查询或数据来触发重新编译。在下面针对1000行表的示例中,使用变量的查询将导致一个计划,该计划估计有300行和一个完整的表扫描,而使用函数调用embedded的查询估计有1行,并执行书签查找。这在第一次运行时是准确的,但在第二次运行时,由于时间的推移,现在所有行都符合条件,它最终会执行1000次这样的随机查找

USE tempdb;

CREATE TABLE [myTable]
(
CreatedDate datetime,
Filler char(8000) NULL
)

CREATE NONCLUSTERED INDEX ix ON [myTable](CreatedDate)

INSERT INTO [myTable](CreatedDate)
/*Insert 1 row that initially qualifies*/
SELECT DATEADD(D,-2001,getdate())
UNION ALL
/*And 999 rows that don't initially qualify*/
SELECT TOP 999 DATEADD(minute,1, DATEADD(D,-2000,getdate()))
FROM master..spt_values

EXEC('
DECLARE @myDate DATETIME = DATEADD(D,-2000,getdate())
SELECT * 
FROM [myTable]  
WHERE CreatedDate <= @myDate
')

EXEC('
SELECT * 
FROM [myTable]  
WHERE CreatedDate <= DATEADD(D,-2000,getdate())
')

RAISERROR ('Delay',0,1) WITH NOWAIT

WAITFOR DELAY '00:01:01'

EXEC('
DECLARE @myDate DATETIME = DATEADD(D,-2000,getdate())
SELECT * 
FROM [myTable]  
WHERE CreatedDate <= @myDate
')

EXEC('
SELECT * 
FROM [myTable]  
WHERE CreatedDate <= DATEADD(D,-2000,getdate())
')

DROP TABLE [myTable]

它不计算where DATEADD每行的值。它是在select甚至开始提取数据之前计算的。这里的问题类似:它不计算where DATEADD every row。它是在select甚至开始提取数据之前计算出来的。这里的问题类似:这是否意味着第一个变量的执行时间有点长?@Yara-取决于选择性。如果查询是高度选择性的,那么第二个可能会考虑一个具有关键查找的计划,这在30%个假设下是极不可能的。实际上,如果你的谓词使用少于CreatedDate,那么它意味着第一个变体有点长的执行时间?如果查询是高度选择性的,那么第二个可能会考虑一个具有关键查找的计划,这在30%个假设下是极不可能的。实际上,如果你的谓词使用少于CreatedDate的谓词。