表值参数性能的问题

时间:2011-05-20 12:21:33

标签: .net sql-server performance sql-server-2008 table-valued-parameters

我不知道这是关于我如何使用它们或Microsoft的实现的问题,但是SQL 2008表值参数非常缓慢。

一般来说,如果我需要使用TVP,那是因为我有很多记录 - 目前看起来它们的速度显然比最少的记录慢得多。

我在.Net这样称呼他们:

// get the data
DataTable data = GetData();

com.CommandText = "sprocName"

// create the table-value parameter
var tvp = com.Parameters.AddWithValue("data", data);
tvp.SqlDbType = SqlDbType.Structured;

com.ExecuteNonQuery();

我运行探查器来查看原因,实际的SQL语句是这样的:

declare @data table ...

insert into @data ( ... fields ... ) values ( ... values ... )
-- for each row
insert into @data ( ... fields ... ) values ( ... values ... )

sprocName(@data)

尽管如此,这是一个非常缓慢的方法。 如果这样做会更快:

insert into @data ( ... fields ... ) 
values ( ... values ... ),
       ( ... values ... ),
       -- for each row
       ( ... values ... )

我不确定为什么它没有使用更新,更快的语法。甚至是SqlBulkCopy引擎盖下的任何内容。

SQL 2008中添加了新语法,但TVP(我认为)也是如此。

有没有选择让它这样做?还是我错过的东西?

2 个答案:

答案 0 :(得分:11)

如果TVP比其他选项“明显慢”,那么很可能你没有正确实现它们。

  1. 您不应该使用DataTable,除非您的应用程序在将值发送到TVP之外使用它。使用IEnumerable<SqlDataRecord>接口更快并且使用更少的内存,因为您不在内存中复制集合仅将其发送到数据库。我在以下地方记录了这一点:
  2. 您不应将AddWithValue用于SqlParameter,但这可能不是性能问题。但是,它应该是:

    SqlParameter tvp = com.Parameters.Add("data", SqlDbType.Structured);
    tvp.Value = MethodThatReturnsIEnumerable<SqlDataRecord>(MyCollection);
    
  3. TVP是表变量,因此不保留统计信息。这意味着,他们报告查询优化器只有1行。所以,在你的过程中,要么:
    • 对使用TVP的任何查询使用语句级重新编译,而不是简单的SELECT:OPTION (RECOMPILE)
    • 创建本地临时表(即单#)并将TVP的内容复制到临时表中
  4. 关于你为什么看到:

    insert into @data ( ... fields ... ) values ( ... values ... )
    -- for each row
    insert into @data ( ... fields ... ) values ( ... values ... )
    

    而不是:

    insert into @data ( ... fields ... ) 
    values ( ... values ... ),
           ( ... values ... ),
    

    如果这实际上是发生了什么,那么:

    • 如果在事务中完成插入,那么就没有真正的性能差异
    • 较新的值列表语法(即VALUES (row1), (row2), (row3))仅限于1000行,因此对于没有该限制的TVP而言,这不是一个可行的选项。

    另请参阅SQL Server客户咨询小组的白皮书:Maximizing Throughput with TVP

答案 1 :(得分:3)

请参阅“表值参数与BULK INSERT操作”部分
http://msdn.microsoft.com/en-us/library/bb510489.aspx

引用:“...表值参数在插入少于1000行时表现良好。”

它还有一个表格,根据插入操作的速度显示要使用的技术。

我希望这有帮助,祝你好运。