假设,将N语句发送到Sql Server(2008)是否更好,或者将包含N语句的1个命令发送到Sql Server更好?在任何一种情况下,我在对象列表上运行相同的语句,在这两种情况下,我将使用命名参数。假设我的用例每隔几个小时就会转储一个日志项缓存。
foreach示例
var sql = "update blah blah blah where id = @id";
using(var conn = GetConnection())
{
foreach(var obj in myList)
{
var cmd = new SqlCommand()
{CommandText = sql, Connection = conn};
//add params from obj
cmd.ExecuteNonQuery();
}
}
批量示例
var sql = @"
update blah blah blah where id = @id1
update blah blah blah where id = @id2
update blah blah blah where id = @id3
-etc";
using (var conn = GetConnection())
{
var cmd = new SqlCommand
{ CommandText = sql, Connection = conn};
for(int i=0; i<myList.Count; i++)
{
//add params: "id" + i from myList[i]
}
cmd.ExecuteNonQuery();
}
在时间测试中,批量版本比大型输入的foreach版本长15%。我认为批处理版本需要更长的时间来执行,因为服务器必须解析一个巨大的语句并绑定多达2000个参数。假设Sql Server在局域网上,使用批处理方法有什么优势吗?
答案 0 :(得分:0)
您的测试似乎已经给了您答案,但让我添加另一个。最好将更新封装到单独的函数中,并使用foreach调用它:
private function UpdateFoo( int id )
{
const sql = "Update Foo Where Id = @Id";
using ( var conn = GetConnection() )
{
using ( var cmd = new SqlCommand( sql, conn ) )
{
cmd.AddParameterWithValue( "@Id", id )
cmd.ExecuteNonQuery();
}
}
}
private function UpdateLotsOfFoo()
{
foreach( var foo in myList )
{
UpdateFoo( foo.Id );
}
}
在此设置中,您正在利用连接池,这可以降低打开和关闭连接的成本。
答案 1 :(得分:0)
@Thomas - 这种设计会增加循环中打开/关闭连接的开销。这不是优选的做法,应该避免。下面的代码允许在使用一个连接时迭代语句,并且在资源(客户端和服务器端)上更容易。
private void UpdateFoo(int id)
{
const string sql = "Update Foo Where Id = @Id";
using (var conn = GetConnection())
{
conn.Open();
foreach (var foo in myList)
{
UpdateFoo(foo.Id);
using (var cmd = new SqlCommand(sql, conn))
{
cmd.AddParameterWithValue("@Id", id);
cmd.ExecuteNonQuery();
}
}
conn.Close();
}
}