Sql server 当涉及变量/函数时,简单的SQL Server查询将永远持续
这是我挣扎了一段时间,但总是能找到解决的办法。 我在SQLServerDW中有一个事实表,它有大约3000万条记录,还有一个名为DateCreatedKey的整数字段,该字段上有一个非聚集索引。 然后我还有一个名为Sql server 当涉及变量/函数时,简单的SQL Server查询将永远持续,sql-server,tsql,Sql Server,Tsql,这是我挣扎了一段时间,但总是能找到解决的办法。 我在SQLServerDW中有一个事实表,它有大约3000万条记录,还有一个名为DateCreatedKey的整数字段,该字段上有一个非聚集索引。 然后我还有一个名为dbo.fn\u DateKeyFromDate的函数,它非常简单 declare @ret int = Year(@date) * 10000 + Month(@date) * 100 + Day(@date) return @ret 从下面的执行时间可以看出,在使用函数或变量时
dbo.fn\u DateKeyFromDate
的函数,它非常简单
declare @ret int = Year(@date) * 10000 + Month(@date) * 100 + Day(@date)
return @ret
从下面的执行时间可以看出,在使用函数或变量时,索引似乎无法正常工作。
不确定我是否遗漏了一些明显的东西
下面是这5段代码的执行时间:
- A:0.034s:
SELECT * INTO #subs2 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= 20170814
declare @fromdate int select @fromdate = 20170814 SELECT * INTO #subs3 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= @fromdate
SELECT * INTO #subs4 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= dbo.fn_DateKeyFromDate(GETDATE()-1)
declare @fromdate int select @fromdate = dbo.fn_DateKeyFromDate(GETDATE()-1) SELECT * INTO #subs FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= @fromdate
- B:15.4s:
SELECT * INTO #subs2 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= 20170814
declare @fromdate int select @fromdate = 20170814 SELECT * INTO #subs3 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= @fromdate
SELECT * INTO #subs4 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= dbo.fn_DateKeyFromDate(GETDATE()-1)
declare @fromdate int select @fromdate = dbo.fn_DateKeyFromDate(GETDATE()-1) SELECT * INTO #subs FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= @fromdate
- C:134s:
SELECT * INTO #subs2 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= 20170814
declare @fromdate int select @fromdate = 20170814 SELECT * INTO #subs3 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= @fromdate
SELECT * INTO #subs4 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= dbo.fn_DateKeyFromDate(GETDATE()-1)
declare @fromdate int select @fromdate = dbo.fn_DateKeyFromDate(GETDATE()-1) SELECT * INTO #subs FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= @fromdate
- D:20s:
SELECT * INTO #subs2 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= 20170814
declare @fromdate int select @fromdate = 20170814 SELECT * INTO #subs3 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= @fromdate
SELECT * INTO #subs4 FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= dbo.fn_DateKeyFromDate(GETDATE()-1)
declare @fromdate int select @fromdate = dbo.fn_DateKeyFromDate(GETDATE()-1) SELECT * INTO #subs FROM biWarehouse.dbo.factSubscriptions WITH (NOLOCK) where DateCreatedKey >= @fromdate
我必须查看C的查询计划,但我假设它会将我指向该函数。但是A很快,因为您使用的是文本,SQL知道如何处理该值 由于使用局部变量,B和D的速度较慢。请看这里: 我可以想象,如果您创建了一个存储过程并传入值,那么您的执行时间将大大减少
或者您可以通过添加一个重新编译查询提示来测试它,这将允许优化器使用正确的统计信息。您可以为一个运行快而慢的查询发布执行计划吗?您可以使用此链接发布计划:我相信您可能有一些数据类型转换。第四个查询与第三个查询相同。也许你可以用A、B、C等标记你的查询,这样我们就可以参考它们了。我知道,在某些情况下,函数不会停止字段的可搜索性,但我还是避免使用它们。您可能会从带有索引的持久化计算列中获得更好的性能。我相信当在where子句中使用
dbo.fn\u DateKeyFromDate(GETDATE()-1)
时,将对每一行求值。查询计划肯定会告诉您。谢谢,这些是指向执行计划的链接。我很好奇:如果您使用SCHEMABINDING声明函数,结果会怎么样?(有关示例,请参阅。)您运行的是哪个版本的SQL Server?(选择@@VERSION
)你说得对,很好。但是,该查询的执行时间仍然是20秒,大约是其应执行时间的600倍be@Niel请记住,在许多其他因素中,服务器缓存可能会改变您看到的结果的速度。如果要了解查询是否正在执行相同的操作,请检查它们的查询计划。