是否可以重新创建许多SQL连接(SQL 2008)

时间:2010-03-27 13:36:13

标签: sql database-design database-connection sharding database-partitioning

当在数据库中执行许多插入时,我通常会有这样的代码:

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();
  }
}

这基本上意味着它为每个项目创建了一个与数据库的新连接。这会起作用还是会为每个插入重建连接会导致可怕的开销?

3 个答案:

答案 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