当在数据库中执行许多插入时,我通常会有这样的代码:
using (var connection = new SqlConnection(connStr))
{
connection.Open();
foreach (var item in items)
{
var cmd = new SqlCommand("INSERT ...")
cmd.ExecuteNonQuery();
}
}
我现在想要对数据库进行分片,因此需要根据要插入的项目选择连接字符串。这会让我的代码更像这样运行
foreach (var item in items)
{
connStr = GetConnectionString(item);
using (var connection = new SqlConnection(connStr))
{
connection.Open();
var cmd = new SqlCommand("INSERT ...")
cmd.ExecuteNonQuery();
}
}
这基本上意味着它为每个项目创建了一个与数据库的新连接。这会起作用还是会为每个插入重建连接会导致可怕的开销?
答案 0 :(得分:4)
我假设你在谈论C#/ .NET。在这种情况下,连接由框架汇集,因此以这种方式创建它们的开销并不高。
正如@TomTom指出的那样,交易也应该考虑在内。如果要在同一服务器上的不同数据库中进行插入,则可以使用普通的SQL事务。如果数据库位于不同的服务器上,则需要使用MSDTC事务在数据库服务器之间协调它们。无论如何,处理事务的最佳方法是将相关代码包装在TransactionScope中。这与打开和关闭(实际上是从池中重用)数据库连接不冲突。
using(new TransactionScope())
{
// Update code to various databases, opening and closing connections.
}
使用SQL2005或更新版本时,TransactionScope将首先默认为SQL事务,然后在需要时自动将其升级为MSDTC事务。
答案 1 :(得分:2)
理论上可以创建尽可能多的连接。除非您强制使用非连接池,否则重新创建连接很快。每个标准SQL连接都没有关闭,而是放入池中(两分钟,iirc)以便重用。
也就是说,如果你为每个插件打开一个新的连接,你会遇到严重的问题 - 你的事务边界。更复杂的更新需要属于一个事务。虽然yoyu CAN只是将它包装在System.Transaction命名空间下... ...这将意味着所有连接将一直保持打开状态,直到提交,使用大量连接,并且它将强制MSDTC(分布式事务处理协调器)介入 - 具有所有开销。
因此,从体系结构的角度来看,重新使用连接是更加可取的你基本上处于事务行为的死胡同,而不是连接数。
答案 2 :(得分:1)
除了其他海报所提出的观点之外,你所说的模式就是你常用的风格让我想起了我刚读过的东西。
http://research.microsoft.com/apps/pubs/?id=76507
2.3识别批量操作的机会
考虑应用程序中的循环 代码,如下所示,里面的 应用程序正在将数据插入到 表:
for (int i=0;i<MAXVALUE;i++) { // execute SQL statement INSERT INTO T VALUES(...) }
如上所述,代码是 因为每次都没有效率 一个INSERT语句循环 执行。一种更有效的方式 达到同样的效果就是使用了 批量插入数据访问的API 层,利用 配料。注意成分 鉴别这个问题 一个应用程序上下文 执行特定的SQL语句 反复在一个循环内,和 知道每个数据库上下文 实例实际上是一个INSERT 表T上的陈述。然后就是 可以放这些 信息一起建议一个 映射到批量插入API。
在ADO.NET 2.0中,我认为这意味着使用SqlBulkCopy