我不知道这是关于我如何使用它们或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(我认为)也是如此。
有没有选择让它这样做?还是我错过的东西?
答案 0 :(得分:11)
如果TVP比其他选项“明显慢”,那么很可能你没有正确实现它们。
IEnumerable<SqlDataRecord>
接口更快并且使用更少的内存,因为您不在内存中复制集合仅将其发送到数据库。我在以下地方记录了这一点:
您不应将AddWithValue
用于SqlParameter,但这可能不是性能问题。但是,它应该是:
SqlParameter tvp = com.Parameters.Add("data", SqlDbType.Structured);
tvp.Value = MethodThatReturnsIEnumerable<SqlDataRecord>(MyCollection);
OPTION (RECOMPILE)
#
)并将TVP的内容复制到临时表中关于你为什么看到:
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行时表现良好。”
它还有一个表格,根据插入操作的速度显示要使用的技术。
我希望这有帮助,祝你好运。