我很确定将参数嗅探添加到表值参数中的价值很小或没有价值但是我想知道是否有人可以证实这一点?
(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
答案 0 :(得分:4)
这没有任何效果 - 事实上,它对性能有害,因为你先复制整个表。
优化器不维护表值参数或表变量的统计信息。这很容易导致错误的查询计划与基数不匹配;解决方案通常是一个中间临时表。在任何情况下,参数嗅探都不是问题 - 表内容从不用于优化查询计划。
顺便提一下,虽然您可以将参数分配给局部变量来规避嗅探,但更灵活的选择是在特别受影响的查询中使用OPTIMIZE FOR
or RECOMPILE
提示(或者WITH RECOMPILE
整体存储程序,但这有点激烈)。这样可以防止程序因所有内容的副本而混乱。
答案 1 :(得分:4)
正如Jeroen已经提到的,TVP没有参数嗅探问题。此外,减轻统计数据缺失的一个选择是将TVP复制到本地临时表(它确实维护统计数据)。
但是,另一个有时更高效的选项是使用表变量(即TVP)对任何查询进行语句级重新编译。不会在查询中维护统计信息,因此需要在任何涉及表变量的查询上完成,而这些查询不是简单的SELECT。
以下说明了此行为:
DECLARE @TableVariable TABLE (Col1 INT NOT NULL);
INSERT INTO @TableVariable (Col1)
SELECT so.[object_id]
FROM [master].[sys].[objects] so;
-- Control-M to turn on "Include Actual Execution Plan".
-- For each of the 3 following queries, hover over the "Table Scan"
-- operator to see the "Estimated Number of Rows".
SELECT * FROM @TableVariable; -- Estimated Number of Rows = 1 (incorrect)
SELECT * FROM @TableVariable
OPTION (RECOMPILE); -- Estimated Number of Rows = 91 (correct)
SELECT * FROM @TableVariable; -- Estimated Number of Rows = 1 (back to incorrect)