所以基本上我有这个相对较长的存储过程.基本的执行流程是将SELECTS INTO
一些数据导入临时表#
,然后用符号声明,然后在这些表中运行游标,生成一个'running total'到第三个临时表中,该表是使用CREATE
.然后,这个生成的临时表与DB中的其他表连接,以在一些分组等之后生成结果.问题是此SP一直运行良好,直到现在返回结果1-2分钟.现在突然间需要12-15分钟.如果我从SP中提取查询并通过手动设置相同的参数在管理工作室中执行它,它会在1-2分钟内返回结果,但SP需要很长时间.知道会发生什么.我试图生成Query和SP的实际执行计划但由于光标而无法生成它.任何想法为什么SP需要这么长时间查询不?
sql sql-server stored-procedures sql-server-2005 parameter-sniffing
对于针对SQL Server 2008 R2运行的实体框架(4.2)生成的简单SQL查询,我遇到了一些主要的性能问题.在某些情况下(但不是全部),EF使用以下语法:
exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE', @param1...
Run Code Online (Sandbox Code Playgroud)
在其他情况下,只需执行原始SQL,并将提供的参数烘焙到查询中.我遇到的问题是使用sp_executesql执行的查询忽略了目标表上的所有索引,导致执行查询极差(通过检查SSMS中的执行计划来确认).
经过一些研究,听起来这个问题可能是由"参数嗅探"造成的.如果我附加OPTION(RECOMPILE)查询提示,如下所示:
exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE OPTION(RECOMPILE)', @param1...
Run Code Online (Sandbox Code Playgroud)
使用目标表上的索引,并且查询执行速度非常快.我还尝试在数据库实例(http://support.microsoft.com/kb/980653)上切换用于禁用参数嗅探(4136)的跟踪标志,但是这似乎没有任何效果.
这给我留下了一些问题:
附加信息:
我还要提一下,如果我通过服务管理控制台重新启动SQL Server服务,在使用下面的脚本启用跟踪标志4136后,实际上似乎清除了跟踪标志...也许我应该以不同的方式这样做......
DBCC TRACEON(4136,-1)
Run Code Online (Sandbox Code Playgroud) entity-framework parameter-sniffing sql-server-2008-r2 sp-executesql
我已经阅读了很多关于参数嗅探的文章,但目前尚不清楚这是好还是坏.任何人都可以通过一个简单的例子来解释
有没有办法自动检测错误的计划分配给特定的声明?
提前致谢.
我在SQL Server 2012中遇到了经典的参数嗅探问题.基于一些研究,我发现了围绕这个问题的多种选择.我需要了解的区别这两个选项是OPTION(OPTIMIZE FOR UNKNOWN)
VS OPTION(RECOMPILE)
.
我犹豫是否OPTION(RECOMPILE)
在我的查询结束时使用这个问题,因为它会强制服务器每次都生成一个新的执行计划.如果我经常调用此查询,这将会占用该计算机的CPU.
因此,我使用他最好的解决方案,这两个选项之间的真正区别是什么?
是否会OPTION(OPTIMIZE FOR UNKNOWN)
重复使用缓存而不是每次重新编译?
我有一个存储过程接受一个日期输入,如果没有传入值,则该日期输入稍后设置为当前日期:
CREATE PROCEDURE MyProc
@MyDate DATETIME = NULL
AS
IF @MyDate IS NULL SET @MyDate = CURRENT_TIMESTAMP
-- Do Something using @MyDate
Run Code Online (Sandbox Code Playgroud)
我遇到问题,如果@MyDate
在NULL
第一次编译存储过程时传入if ,则对于所有输入值(NULL
或其他),性能总是很糟糕,如果在编译存储过程时传入日期/当前日期性能适用于所有输入值(NULL
或其他).
令人困惑的是,即使实际 使用@MyDate的值NULL
(而不是CURRENT_TIMESTAMP
由IF语句设置),生成的糟糕执行计划也很糟糕
我发现禁用参数嗅探(通过欺骗参数)修复了我的问题:
CREATE PROCEDURE MyProc
@MyDate DATETIME = NULL
AS
DECLARE @MyDate_Copy DATETIME
SET @MyDate_Copy = @MyDate
IF @MyDate_Copy IS NULL SET @MyDate_Copy = CURRENT_TIMESTAMP
-- Do Something using @MyDate_Copy
Run Code Online (Sandbox Code Playgroud)
我知道这与参数嗅探有关,但我看到的所有"参数嗅探变坏"的例子都涉及使用传递的非代表性参数编译存储过程,但是在这里我看到了执行计划是可怕的SQL Server可能认为执行该语句其中参数可能需要在该点所有可能的值- NULL
,CURRENT_TIMESTAMP
或以其他方式.
有没有人知道为什么会这样?
我在SQL Server 2012中有一个多租户数据库,其中每个租户的行由一tenant_id
列(即共享数据库,共享模式方法)标识.一些租户,特别是较新的租户,行数很少,而其他租户则很多.
SQL Server的查询优化器通常根据第一次执行时提供的参数构建查询计划,然后即使提供了不同的参数,也可以将此计划重新用于所有将来的查询.这称为参数嗅探.
我们在数据库中遇到的问题是SQL Server有时会根据指向较小租户的参数构建这些计划,这对于该租户很有效,但是当它将缓存计划重新应用于更大的租户时,它会发生灾难性的失败(通常是时间安排)事实上).通常情况下,只有当我们的一个大租户与我们联系遇到超时错误时才会发现这种情况,然后我们必须进入系统并手动清除所有查询计划以纠正它.
您可以使用查询提示来阻止SQL Server缓存查询计划(OPTIMIZE FOR UNKNOWN
),但这会导致一些额外的开销,因为每次调用查询时都会重新生成查询计划.另一个问题是我们使用的Entity Framework无法指定OPTIMIZE FOR UNKNOWN
查询提示.
所以问题是 - 关于参数嗅探的多租户数据库的最佳实践是什么?有没有办法在数据库范围内禁用参数嗅探而无需在每个查询中指定它?如果是这样,这是最好的方法吗?我应该以其他方式对数据进行分区吗?还有其他一些我没想到的方法吗?
sql-server performance entity-framework parameter-sniffing multi-tenant
今天再次,我有一个主要问题,似乎是SQL Server 2005中的参数嗅探.
我有一个查询将一些结果与已知的良好结果进行比较.我在结果和已知的良好结果中添加了一列,因此每个月,我可以在双方加载新月结果并仅比较当前月份.新列首先出现在聚簇索引中,因此新月将添加到结尾.
我为my WHERE
子句添加了一个标准- 这是代码生成的,所以它是一个文字常量:
WHERE DATA_DT_ID = 20081231
- 这是多余的,因为所有DATA_DT_ID现在都是20081231.
性能进入底池.从7秒开始比较大约1.5米行到2小时并没有完成任何事情.在SSMS中运行生成的SQL权限 - 没有SP.
我一直在使用SQL Server已经12年了,我从来没有遇到过如此多的参数嗅探问题,就像我自10月以来在这个生产服务器上所做的那样(构建版本9.00.3068.00).并且在每种情况下,都不是因为它是第一次使用不同的参数运行或表格已更改.这是一个新表,它只使用此参数或根本没有WHERE
子句运行.
而且,不,我没有DBA访问权限,他们没有给我足够的权利来查看执行计划.
到目前为止,我不确定我是否能够只用几年的经验将这个系统交给SQL Server用户.
更新事实证明,虽然统计数据声称是最新的,但运行UPDATE STATISTICS WITH FULLSCAN可以解决问题.
最终更新即使重新创建SP,使用WITH RECOMPILE和UPDATE STATISTICS,结果是必须以不同的方式重写查询以使用NOT IN而不是使用NULL检查LEFT JOIN.
我相当肯定将参数嗅探添加到表值参数几乎没有价值,但是我想知道是否有人可以确认这一点?
(INT_LIST 是用户定义的表类型,它是 INT 类型的单列)
CREATE PROCEDURE [dbo].[TVPSniffTest](
@param1 varchar(50),
@idList INT_LIST readonly
)
AS
BEGIN
DECLARE @param1_sniff VARCHAR(50) = @param1 --this is worth doing
DECLARE @idList_sniff INT_LIST
INSERT INTO @idList_sniff SELECT value FROM @idList --will this help?
--query code here
END
Run Code Online (Sandbox Code Playgroud) 当我的一个查询执行时间比预期长得多时,我遇到了参数嗅探.当我深入研究这个问题时,我开始知道:
当第一次执行查询时,它(SQL Server)为该查询创建执行计划,并且执行相同查询的其他n次,如果在第一次执行时结果集中存在较大差异,则会出现参数嗅探问题.
这是我的方案.
现在我的问题是,在这些情况下,有没有办法或解决方法来克服SQL Server中的参数嗅探?
我知道通过跑步sp_updatestats
我可以验证它是否正在发生.
同时,我知道要赶上这个问题,我需要监控过程高速缓存,通过query_hash
和query_plan_hash
领域sys.dm_exec_query_stats
我可以做到这一点.
我不想RECOMPILE
在SET
变量部分中使用,因为这将在每次执行查询时创建新的执行计划.
但是,我不是通过在查询本身做一些事情来验证我想要克服它的问题,而是"例如"在运行时检测问题并仅在需要时创建新的执行计划(不是每次都)".
我经常面对参数嗅探问题,所以非常感谢每一个有用的建议和帮助.提前致谢!
PostgreSQL 中的准备和执行组合允许使用绑定参数。但是,Prepare 不会生成针对一组参数绑定进行优化的计划,该计划可以与另一组参数绑定一起重用。有人对实现此类功能有指导吗?这样,该计划将针对给定的一组参数绑定进行优化,但可以重用于另一组。该计划对于后续集合可能效率不高,但如果使用新参数绑定重新计算计划成本,则可能会发现它是有效的。
读取和使用参数绑定值进行基数估计在 SQL Server 中称为“参数嗅探”,在 Oracle 中称为“绑定窥视”。基本上,有没有人在 PostgreSQL 中做过类似的事情。