SQL 当约束被硬编码时,服务器在 WHERE 子句中的不同性能
SQL Server different performance in a WHERE clause when constraint is hardcoded
我在 SQL Server 2014 上遇到了一个非常奇怪的性能问题。我尝试 select 一些基于约束特定日期记录的 where 子句的值。当我对日期进行硬编码时,查询很快(3 秒),而当我尝试参数化查询时,它很慢。
为了以防万一,时间戳上有一个索引。您将在下面找到不同的查询及其性能。
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp]>='2016-07-25' AND [Timestamp]<'2016-07-26'
--execution time 3 seconds!
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp] BETWEEN '2016-07-25' AND '2016-07-26'
--execution time 3 seconds!
DECLARE @StartDate DATETIME
SET @StartDate = '2016-07-25'
DECLARE @StartDateString VARCHAR(10)
SET @StartDateString =CAST(FORMAT(@StartDate,'yyyy-MM-dd HH:mm:ss.fff') AS VARCHAR(10))
DECLARE @EndDateString VARCHAR(10)
SET @EndDateString =CAST(FORMAT(DATEADD(day,1,@StartDate),'yyyy-MM-dd HH:mm:ss.fff') AS VARCHAR(10))
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp] BETWEEN @StartDateString AND @EndDateString
--execution time 30 minutes!
DECLARE @StartDate DATETIME
SET @StartDate = '2016-07-25'
DECLARE @EndDate DATETIME
SET @EndDate =DATEADD(day,1,@StartDate)
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp] BETWEEN @StartDate AND @EndDate
--execution time 30 minutes!
请参阅下面 TT 的回答,了解除了构建查询之外的替代解决方案
DECLARE @StartDate DATETIME
SET @StartDate = '2016-07-25'
DECLARE @EndDate DATETIME
SET @EndDate =DATEADD(day,1,@StartDate)
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp] BETWEEN @StartDate AND @EndDate
OPTION(RECOMPILE)
--execution time 3 sec
我找到了解决方法。我构建了查询并执行了它。不过,如果您知道性能不同的原因,请告诉我。
DECLARE @StartDate DATETIME
SET @StartDate = '2016-07-25'
DECLARE @StartDateString VARCHAR(10)
SET @StartDateString =CAST(FORMAT(@StartDate,'yyyy-MM-dd HH:mm:ss.fff') AS VARCHAR(10))
DECLARE @EndDateString VARCHAR(10)
SET @EndDateString =CAST(FORMAT(DATEADD(day,1,@StartDate),'yyyy-MM-dd HH:mm:ss.fff') AS VARCHAR(10))
DECLARE @Query NVARCHAR(4000)
SET @Query =
'
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp]>='''+@StartDateString+''' AND [Timestamp]<'''+@EndDateString+'''
'
EXECUTE sp_executesql @Query
首先,我会为您的参数使用 DATETIME
类型。
其次,您很有可能 运行正在研究参数嗅探。使用 Query Hints:
回避此问题的两种方法
- 向查询添加查询提示
OPTION(RECOMPILE)
- 向查询添加查询提示
OPTION(OPTIMIZE FOR UNKNOWN)
第一个选项仅适用于不经常 运行 的查询(>> 1/秒),而第二个选项在很多情况下更受欢迎。
我在 SQL Server 2014 上遇到了一个非常奇怪的性能问题。我尝试 select 一些基于约束特定日期记录的 where 子句的值。当我对日期进行硬编码时,查询很快(3 秒),而当我尝试参数化查询时,它很慢。
为了以防万一,时间戳上有一个索引。您将在下面找到不同的查询及其性能。
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp]>='2016-07-25' AND [Timestamp]<'2016-07-26'
--execution time 3 seconds!
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp] BETWEEN '2016-07-25' AND '2016-07-26'
--execution time 3 seconds!
DECLARE @StartDate DATETIME
SET @StartDate = '2016-07-25'
DECLARE @StartDateString VARCHAR(10)
SET @StartDateString =CAST(FORMAT(@StartDate,'yyyy-MM-dd HH:mm:ss.fff') AS VARCHAR(10))
DECLARE @EndDateString VARCHAR(10)
SET @EndDateString =CAST(FORMAT(DATEADD(day,1,@StartDate),'yyyy-MM-dd HH:mm:ss.fff') AS VARCHAR(10))
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp] BETWEEN @StartDateString AND @EndDateString
--execution time 30 minutes!
DECLARE @StartDate DATETIME
SET @StartDate = '2016-07-25'
DECLARE @EndDate DATETIME
SET @EndDate =DATEADD(day,1,@StartDate)
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp] BETWEEN @StartDate AND @EndDate
--execution time 30 minutes!
请参阅下面 TT 的回答,了解除了构建查询之外的替代解决方案
DECLARE @StartDate DATETIME
SET @StartDate = '2016-07-25'
DECLARE @EndDate DATETIME
SET @EndDate =DATEADD(day,1,@StartDate)
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp] BETWEEN @StartDate AND @EndDate
OPTION(RECOMPILE)
--execution time 3 sec
我找到了解决方法。我构建了查询并执行了它。不过,如果您知道性能不同的原因,请告诉我。
DECLARE @StartDate DATETIME
SET @StartDate = '2016-07-25'
DECLARE @StartDateString VARCHAR(10)
SET @StartDateString =CAST(FORMAT(@StartDate,'yyyy-MM-dd HH:mm:ss.fff') AS VARCHAR(10))
DECLARE @EndDateString VARCHAR(10)
SET @EndDateString =CAST(FORMAT(DATEADD(day,1,@StartDate),'yyyy-MM-dd HH:mm:ss.fff') AS VARCHAR(10))
DECLARE @Query NVARCHAR(4000)
SET @Query =
'
SELECT *
FROM [DB].[schema].[table]
WHERE [Timestamp]>='''+@StartDateString+''' AND [Timestamp]<'''+@EndDateString+'''
'
EXECUTE sp_executesql @Query
首先,我会为您的参数使用 DATETIME
类型。
其次,您很有可能 运行正在研究参数嗅探。使用 Query Hints:
回避此问题的两种方法- 向查询添加查询提示
OPTION(RECOMPILE)
- 向查询添加查询提示
OPTION(OPTIMIZE FOR UNKNOWN)
第一个选项仅适用于不经常 运行 的查询(>> 1/秒),而第二个选项在很多情况下更受欢迎。