【问题标题】:Table Valued Parameters with Estimated Number of Rows 1具有估计行数的表值参数 1
【发布时间】:2014-04-16 21:19:37
【问题描述】:

我已经在互联网上搜索了几个小时,试图弄清楚如何使用表值参数 (TVP) 来提高我的查询性能。

经过几个小时的搜索,我终于确定了我认为问题的根源。在检查我的查询的估计执行计划后,我发现每当我使用 TVP 时,我的查询的估计行数为 1。如果我将 TVP 交换为选择我感兴趣的数据的查询,那么估计的行数在 7400 左右会更加准确。这会显着提高性能。

但是,在实际场景中,我不能使用查询,我必须使用 TVP。在使用 TVP 时,有什么方法可以让 SQL Server 更准确地预测行数,以便使用更合适的计划?

【问题讨论】:

  • 你能在表值变量上使用更新统计信息吗?
  • @Dannyg9090 不,临时变量不存储统计信息。

标签: sql sql-server-2008 sql-execution-plan table-valued-parameters


【解决方案1】:

TVP 是不维护统计信息的表变量,因此报告只有 1 行。有两种方法可以改善 TVP 的统计数据:

  1. 如果您不需要修改 TVP 中的任何值或向其中添加列来跟踪操作数据,那么您可以对任何使用表变量 (TVP) 的查询执行简单的语句级OPTION (RECOMPILE)或本地创建),并且使用该表变量比简单的 SELECT 执行更多操作(即执行 INSERT INTO RealTable (columns) SELECT (columns) FROM @TVP; 不需要语句级重新编译)。在 SSMS 中执行以下测试以查看此行为的实际效果:

    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"
    
    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)
    
  2. 创建一个本地临时表(单个#)并将TVP 数据复制到该表。虽然这确实复制了tempdb 中的数据,但好处是:

    • 与表变量相比,临时表的统计数据更好(即不需要语句级重新编译)
    • 能够添加列
    • 修改值的能力

【讨论】:

  • RECOMPILE 真的能解决估计问题吗?没有 TVP 的统计数据。
  • @usr 是的,statement-level RECOMPILE 确实为该查询获取了正确的行数。因为没有为表变量维护统计信息,所以不幸的是,行数没有被带到引用该表变量的后续查询中。我已经用一个表明它有效的测试更新了我的答案。
  • @usr 是的,这是 Aaron Bertrand sqlperformance.com/2014/06/t-sql-queries/…的一篇很棒的文章@
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 2016-08-24
  • 2023-03-11
  • 2023-03-26
  • 1970-01-01
相关资源
最近更新 更多