Kei*_*ith 13 .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();
Run Code Online (Sandbox Code Playgroud)
我运行探查器来查看原因,实际的SQL语句是这样的:
declare @data table ...
insert into @data ( ... fields ... ) values ( ... values ... )
-- for each row
insert into @data ( ... fields ... ) values ( ... values ... )
sprocName(@data)
Run Code Online (Sandbox Code Playgroud)
尽管如此,这是一个非常缓慢的方法.如果这样做会更快:
insert into @data ( ... fields ... )
values ( ... values ... ),
( ... values ... ),
-- for each row
( ... values ... )
Run Code Online (Sandbox Code Playgroud)
我不确定为什么它没有使用更新,更快的语法.甚至无论它在引擎盖下做什么SqlBulkCopy.
在SQL 2008中添加了新语法,但TVP(我认为)也是如此.
有没有选择让它这样做?还是我错过的东西?
Sol*_*zky 14
如果TVP比其他选项"明显慢",那么很可能你没有正确实现它们.
IEnumerable<SqlDataRecord>接口更快并且使用更少的内存,因为您不在内存中复制集合仅将其发送到数据库.我在以下地方记录了这一点:
您不应该使用AddWithValueSqlParameter,尽管这可能不是性能问题.但是,它应该是:
SqlParameter tvp = com.Parameters.Add("data", SqlDbType.Structured);
tvp.Value = MethodThatReturnsIEnumerable<SqlDataRecord>(MyCollection);
Run Code Online (Sandbox Code Playgroud)OPTION (RECOMPILE)#)并将TVP的内容复制到临时表中关于你为什么看到:
insert into @data ( ... fields ... ) values ( ... values ... )
-- for each row
insert into @data ( ... fields ... ) values ( ... values ... )
Run Code Online (Sandbox Code Playgroud)
代替:
insert into @data ( ... fields ... )
values ( ... values ... ),
( ... values ... ),
Run Code Online (Sandbox Code Playgroud)
如果这实际上是发生了什么,那么:
VALUES (row1), (row2), (row3))限于1000行,因此对于没有该限制的TVP而言不是可行的选项.另请参阅SQL Server客户咨询团队的白皮书:使用TVP最大化吞吐量
请参阅“表值参数与 BULK INSERT 操作”部分
http://msdn.microsoft.com/en-us/library/bb510489.aspx
引用:“...表值参数在插入少于 1000 行时表现良好。”
它还有一个表格来显示根据插入操作的速度使用什么技术。
我希望这会有所帮助,祝你好运。
| 归档时间: |
|
| 查看次数: |
5208 次 |
| 最近记录: |