表值参数的参数嗅探

Señ*_*age 4 parameter-sniffing sql-server-2008 table-valued-parameters

我相当肯定将参数嗅探添加到表值参数几乎没有价值,但是我想知道是否有人可以确认这一点?

(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)

Sol*_*zky 5

正如 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)
Run Code Online (Sandbox Code Playgroud)


Jer*_*ert 4

这没有任何影响——事实上,它对性能有害,因为您首先复制整个表。

优化器不维护表值参数或表变量的统计信息。这很容易导致基数不匹配的错误查询计划;解决方案通常是中间临时表。无论如何,参数嗅探都不会成为问题——表内容永远不会用于优化查询计划。

顺便说一句,虽然您可以将参数分配给局部变量来规避嗅探,但更灵活的选择是在特别受影响的查询中使用OPTIMIZE FORRECOMPILEWITH RECOMPILE提示(或在整个存储过程上,但这有点更激烈)。这可以防止所有内容的副本弄乱整个过程。

  • 好信息。我意识到你确实有资格在整个过程中使用“WITH RECOMPILE”,但这可能应该多强调一点,因为在被调用很多次(即每分钟多次或更多)的过程中这样做会显示出明显的性能下降。不过,+1。 (2认同)