1

ac# アプリケーションを使用して多数のデータ行をデータベース (SQL 2008 R2) にコミットするコードに問題があります。

私が今行っていることは、データベースに挿入する必要がある約 40.000 行を含むかなり大きな XML ファイル (約 30Mb) を作成していることです。

変数としてデータベースに渡すこの xml ドキュメントから、データを読み取り、適切な挿入または更新を行うストアド プロシージャがあります。

疑似 c# コード:

String xml = xmlWriter.ToString();
SqlCommand cmd = new SqlCommand("sp_CommitData", connection)
cmd.Variables.AddWithValue("@xml", xml);
SqlDataReader reader = cmd.ExecuteReader();
while(reader.Read())
{ 
 /* Read return data */
}

疑似 tsql コード:

INSERT INTO DataTable
xmldata.value('@uID','[uniqueidentifier]') AS [uID]
FROM<
@xml.nodes('/data/m/r') [xmldata](xmldata)  

このアプローチは過去に私にとってはかなりうまくいきましたが、今ではアプローチが機能するにはデータが膨大に見えます...データをコミットするだけで3分以上かかり、それは長い道のりです。:(

これは非常に一般的な問題に違いありません。同様のシナリオで皆さんはどのように対処しますか? C# でかなり大量のデータをコミットする方法について何か良い指針はありますか。ソリューションはスレッドセーフでなければならないので、私は bcp や同様のアプローチにはあまり興味がありません。

よろしく ドリュー

4

2 に答える 2

5

これを行う最速の方法は、SQL の一括読み込み機能を使用するSqlBulkCopyを使用することです。

XML アプローチの問題は、最初に行セット/IEnumerable (正確には何から始めなければならないのでしょうか?) から XML に変換してから、それをネットワーク経由でプッシュする必要があることです。XMLは、それを行うには非常に肥大化した形式であり、言及したように多くの行がある場合にカウントされます。

一括コピー アプローチを使用すると、すべてを (メモリまたはディスクに) 実体化する必要なく、行ごとにストリーミングできるため、メモリ フットプリントを抑えることができます。

データの量が非常に大きい場合は、最初に一時テーブルにロードして (実際のテーブルのトランザクションがないため)、それを実際のものに挿入 (またはMerge ) することをお勧めします。

スレッドセーフとはどういう意味ですか? この操作でクライアントをブロックしないようにする場合は、バックグラウンド スレッドで簡単に開始できます。これを行うために開始する必要がある外部プロセスや何もありません。インプロセスで実行されます。

于 2013-03-05T13:05:09.283 に答える
0

この問題へのご意見ありがとうございます。SqlBulkCopyを調べ始めましたが、ロジックの近くでデータを実行するストアドプロシージャが必要なため、しばらくして停止しました。
データを保存するサービスへの同時スレッドが多数ある可能性があることを考えると、一時テーブルにデータを入力して、後でこれからデータを読み取ることはできません。

次に、テーブル値パラメーターに注意を向け、そこで答えを見つけました。それが非常にうまくいったので、私はこれまでこれを試したことがないことにちょっと驚いています。パフォーマンスの数値では、保存は約45秒から5秒未満になりました。

私をこの方向に向けてくれてありがとう。

于 2013-03-06T13:01:33.340 に答える