Ton*_*llo 4 sql t-sql sql-server
我有一个包含两个 DATE 参数的查询,如下所示:
@startDate DATE,
@endDate DATE
Run Code Online (Sandbox Code Playgroud)
在开发存储过程时,它非常棒(< 1 秒)。小时候把它移到存储过程中,当我再次运行它时,需要几分钟才能运行(确切地说是 2 分钟)。
我之前遇到过这个问题(我认为这是我当时没有追究的一些异常现象),所以我尝试了最后一个有效的“黑客”:
DECLARE @sDate DATE = CAST(@startDate AS DATE);
DECLARE @eDate DATE = CAST(@endDate AS DATE);
Run Code Online (Sandbox Code Playgroud)
果然,返回时间小于 1 秒。
我已经尝试了一切来解决这个问题,但似乎没有任何效果。我找不到任何改变任何东西的差异。无论我尝试以多少种不同的方式对其进行切片,这些值都是完全相同的。
我也尝试过:
SET @startDate = CAST(@startDate AS DATE);
SET @startDate = CONVERT(date, @startDate, 101)
Run Code Online (Sandbox Code Playgroud)
我尝试在父存储过程中重新声明它们(使用任何方法)。
仅当我重新声明子存储过程中的变量时,它才有效。
那么,为什么重新声明相同类型的变量会导致性能如此巨大的差异呢?
我最初并不这么认为,但所有证据都表明事实确实如此,尽管我无法使用通常有效或有助于识别它的正常方法来修复它。除了用局部变量替换它之外,在下面所有海报的帮助下,它表明它必须是参数嗅探。
第一次更新
我不认为这是参数嗅探——这是我的第一个想法。这就是我所做的测试:
上述更改对查询没有影响。
这是一种“参数嗅探”解决方法。我建议阅读:应用程序慢,SSMS 快?
参数和变量
考虑 Northwind 数据库中的 Orders 表,以及以下三个过程:
CREATE PROCEDURE List_orders_1 AS
SELECT * FROM Orders WHERE OrderDate > '20000101'
go
CREATE PROCEDURE List_orders_2 @fromdate datetime AS
SELECT * FROM Orders WHERE OrderDate > @fromdate
go
CREATE PROCEDURE List_orders_3 @fromdate datetime AS
DECLARE @fromdate_copy datetime
SELECT @fromdate_copy = @fromdate
SELECT * FROM Orders WHERE OrderDate > @fromdate_copy
go
Run Code Online (Sandbox Code Playgroud)
在第一个过程中,日期是一个常量,这意味着 SQL Server 只需要考虑这种情况。它询问 Orders 表的统计信息,该统计信息表明没有 OrderDate 为第三个千年的行。(Northwind 数据库中的所有订单都是从 1996 年到 1998 年。)由于统计数据就是统计数据,SQL Server 无法确定查询根本不会返回任何行,因此它只估计一行。
在 List_orders_2 的情况下,查询针对变量,或更准确地说是针对参数。执行优化时,SQL Server 知道该过程是使用值 2000-01-01 调用的。由于它不执行任何流分析,因此无法确定执行查询时参数是否具有该值。尽管如此,它还是使用输入值来进行估计,这与 List_orders_1 相同:一行。这种在优化存储过程时查看输入参数值的策略称为参数嗅探。
在最后一个过程中,一切都不同了。输入值被复制到局部变量,但是当 SQL Server 构建计划时,它对此并不了解,并且对自己说我不知道这个变量的值是什么。
...
关键点
在本节中,我们学到了三件非常重要的事情:
- 常量就是常量,当查询包含常量时,SQL Server 可以完全信任地使用该常量的值,甚至可以采用这样的快捷方式根本不访问表,如果它可以从约束推断出没有行将被退回。
- 对于参数,SQL Server 不知道运行时值,但它在编译查询时“嗅探”输入值。
-对于局部变量,SQL Server 完全不知道运行时值,并应用标准假设。(哪些假设取决于运算符以及可以从唯一索引的存在中推断出什么。)
第二篇好文章参数嗅探问题和可能的解决方法
| 归档时间: |
|
| 查看次数: |
2277 次 |
| 最近记录: |