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

发布于 2024-08-26 14:31:24 字数 627 浏览 9 评论 0 原文

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

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

这基本上意味着它正在为每个项目创建一个到数据库的新连接。这会起作用吗?或者为每个插入重新创建连接会导致可怕的开销吗?

When performing many inserts into a database I would usually have code like this:

using (var connection = new SqlConnection(connStr))
{
  connection.Open();
  foreach (var item in items)
  {
     var cmd = new SqlCommand("INSERT ...")
     cmd.ExecuteNonQuery();
  }
}

I now want to shard the database and therefore need to choose the connection string based on the item being inserted. This would make my code run more like this

foreach (var item in items)
{
  connStr = GetConnectionString(item);
  using (var connection = new SqlConnection(connStr))
  {
    connection.Open();      
    var cmd = new SqlCommand("INSERT ...")
    cmd.ExecuteNonQuery();
  }
}

Which basically means it's creating a new connection to the database for each item. Will this work or will recreating connections for each insert cause terrible overhead?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

与他有关 2024-09-02 14:31:24

我假设您正在谈论 C#/.NET。在这种情况下,连接由框架池化,因此以这种方式创建连接的开销并没有那么高。

编辑

正如@TomTom 指出的那样,事务也应该考虑在内。如果您要向同一服务器上的不同数据库进行插入,则可以使用普通的 SQL 事务。如果数据库位于不同的服务器上,您将需要使用 MSDTC 事务来跨数据库服务器协调它们。无论如何,处理事务的最佳方法是将相关代码包装在 TransactionScope 中。这与打开和关闭(实际上从池中重用)数据库连接并不冲突。

using(new TransactionScope())
{
    // Update code to various databases, opening and closing connections.
}

对于 SQL2005 或更高版本,TransactionScope 将首先默认为 SQL 事务,然后根据需要自动将其升级为 MSDTC 事务。

I assume you are talking about C#/.NET. In that case the connections are pooled by the framework, so the overhead of creating them that way isn't that high.

Edit

As pointed out by @TomTom transactions should also be taken into considerations. If you are doing inserts into different databases on the same server you can use a normal SQL transaction for that. If the databases are on different servers you would need to use an MSDTC transaction for coordinating them across the database servers. Anyways the best way to handle transactions are by wrapping the relevant code in a TransactionScope. This doesn't conflict with opening and closing (in reality reusing from a pool) database connections.

using(new TransactionScope())
{
    // Update code to various databases, opening and closing connections.
}

With SQL2005 or newer the TransactionScope will default to a SQL Transaction first and then automatically escalate it to an MSDTC transaction if needed.

说谎友 2024-09-02 14:31:24

理论上,可以创建任意数量的连接。重新创建连接很快,除非您强制使用非连接池。每个标准 SQL 连接不会关闭,而是放入池中(两分钟,iirc)以供重用。

也就是说,如果您为每个插入打开一个新连接,您就会遇到严重的问题 - 您的事务边界。更复杂的更新需要属于一项事务。虽然 yoyu 可以将其包装在 System.Transaction 命名空间下......
...这将意味着所有连接将保持打开状态直到提交,从而耗尽其中的大量连接,并且将迫使 MSDTC(分布式事务协调器)介入 - 并承担其所有开销。

因此,从体系结构的角度来看,重用连接更为明智。您基本上处于事务行为的死胡同,而不是连接计数的死胡同。

Theoretically it is ok to create as many connections as you wanr. Recreating a connection is fast, unless you force non-connection pooling. Per standard SQL connections are not closed but put into a pool (for two minutes, iirc) for reuse.

That said, if you open a new connection for every insert you run into a serious problems with - your transaction boundaries. More complex updates need to fall under one transaction. While yoyu CAN just wrap that under a System.Transaction namespace...
...it will mean that all the connections will stay open until commit, using up a LOT of them, and it is going to force MSDTC (Distributed Transaction Coordinator) to step in - with all the overhead it has.

As such, reusing connections is a lot more advisable from an architectural point of view You basically are on a dead end with your transactional behavior, not with the connection count.

野味少女 2024-09-02 14:31:24

除了其他海报提出的观点之外,你所说的你惯用的风格让我想起了我刚刚读过的东西。

http://research.microsoft.com/apps/pubs/?id=76507< /a>

2.3 识别批量操作的机会

考虑应用程序中的循环
代码如下所示,其中
应用程序正在将数据插入到
表:

for (int i=0;i

如上面所写,代码是
效率低下,因为每次通过
INSERT 语句的循环是
被执行。一种更有效的方法
达到相同的结果是使用
数据访问的批量插入API
层,它利用
批处理。注意成分
为了识别这个问题有
应用程序上下文
执行特定的SQL语句
在循环内重复进行,并且
数据库上下文知道每个
实例实际上是一个 INSERT
表 T 上的语句。那么
可以把这些碎片
信息一起提出建议
映射到批量插入 API。

在 ADO.NET 2.0 中,我认为这意味着使用 SqlBulkCopy

In addition to the points made by the other posters the pattern you say is your usual style reminds me of something I just read.

http://research.microsoft.com/apps/pubs/?id=76507

2.3 Identifying Opportunities for Bulk Operations

Consider a loop in the application
code, shown below, inside which the
application is inserting data into a
table:

for (int i=0;i<MAXVALUE;i++) {
// execute SQL statement INSERT INTO T VALUES(...)
}

As written above, the code is
inefficient since each time through
the loop an INSERT statement is
executed. A much more efficient way to
achieve the same result is to use the
bulk insert APIs of the data access
layer, which takes advantage of
batching. Note that the ingredients
for identifying this problem is having
the application context that a
particular SQL statement is executed
repeatedly inside a loop, and the
database context to know that each
instance is in fact an INSERT
statement on a table T. It is then
possible to put these pieces of
information together to suggest a
mapping to the bulk insert APIs.

In ADO.NET 2.0 I think this means using SqlBulkCopy

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文