1

データベースへの多くの挿入を実行するとき、私は通常次のようなコードを持っています:

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

これは基本的に、アイテムごとにデータベースへの新しい接続を作成することを意味します。これは機能しますか、それとも挿入ごとに接続を再作成すると、ひどいオーバーヘッドが発生しますか?

4

3 に答える 3

3

あなたはC#/。NETについて話していると思います。その場合、接続はフレームワークによってプールされるため、そのように接続を作成するオーバーヘッドはそれほど高くありません。

編集

@TomTomで指摘されているように、トランザクションも考慮に入れる必要があります。同じサーバー上の異なるデータベースに挿入を行う場合は、通常のSQLトランザクションを使用できます。データベースが異なるサーバー上にある場合は、データベースサーバー間でデータベースを調整するためにMSDTCトランザクションを使用する必要があります。とにかく、トランザクションを処理する最良の方法は、関連するコードをTransactionScopeでラップすることです。これは、データベース接続の開閉(実際にはプールからの再利用)と競合しません。

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

SQL2005以降では、TransactionScopeは最初にデフォルトでSQLトランザクションになり、必要に応じて自動的にMSDTCトランザクションにエスカレートします。

于 2010-03-27T13:40:07.360 に答える
1

理論的には、必要な数の接続を作成することは問題ありません。非接続プーリングを強制しない限り、接続の再作成は高速です。標準のSQL接続では、接続は閉じられませんが、再利用のためにプールに入れられます(2分間、iirc)。

とはいえ、挿入ごとに新しい接続を開くと、トランザクションの境界で深刻な問題が発生します。より複雑な更新は、1つのトランザクションに分類される必要があります。yoyuはそれをSystem.Transaction名前空間でラップすることができますが......これは、すべての接続がコミットされるまで開いたままになり、それらの多くを使い果たし、MSDTC(分散トランザクションコーディネーター)を強制することを意味しますステップインする-それが持っているすべてのオーバーヘッドで。

そのため、アーキテクチャの観点からは、接続を再利用することをお勧めします。基本的に、接続数ではなく、トランザクションの動作が行き詰まっています。

于 2010-03-27T13:42:58.377 に答える
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ステートメントがループ内で繰り返し実行されるアプリケーションコンテキストと、各インスタンスが実際にテーブルTのINSERTステートメントであることを認識するデータベースコンテキストを持つことです。これらの情報を組み合わせて、一括挿入APIへのマッピングを提案します。

ADO.NET 2.0では、これは使用することを意味すると思いますSqlBulkCopy

于 2010-03-27T18:54:43.060 に答える