2012-02-03 3 views
1

コード内のコードセクションを抽出して、複数のスレッドで実行することはできますか?マルチスレッド、DataReaders&一括挿入...このアプリケーションをマルチスレッド化できますか?

ネットワーク上で私たちのSQLサーバーへのDBのFoxProからのデータの上にアプリをコピー(ファイルは非常に巨大であるので、一括コピーが単位で発生する必要があります...

それは動作しますが、私が欲しいです速度を少しアップバンプする。

1)のいずれかによって、私は複数のスレッドで実行され、または代替としてマークされたセクション、

2)のDataRowの各列を介していないループを有する

私は2番目の選択肢に行きました...(以下のコードを更新しました)

CODE

private void BulkCopy(OleDbDataReader reader, string tableName, Table table) 
    { 
     if (Convert.ToBoolean(ConfigurationManager.AppSettings["CopyData"])) 
     { 
      Console.WriteLine(tableName + " BulkCopy Started."); 
      try 
      { 
       DataTable tbl = new DataTable(); 
       foreach (Column col in table.Columns) 
       { 
        tbl.Columns.Add(col.Name, ConvertDataTypeToType(col.DataType)); 
       } 

       int batch = 1; 
       int counter = 0; 

       DataRow tblRow = tbl.NewRow(); 

       while (reader.Read()) 
       { 
        counter++;     
////This section changed 
         object[] obj = tblRow.ItemArray; 
         reader.GetValues(obj); 
         tblRow.ItemArray = obj; 
////********** 
        tbl.LoadDataRow(tblRow.ItemArray, true); 

        if (counter == BulkInsertIncrement) 
        { 
         Console.WriteLine(tableName + " :: Batch >> " + batch); 
         counter = PerformInsert(tableName, tbl, batch); 
         batch++; 
        } 
       } 

       if (counter > 0) 
       { 
        Console.WriteLine(tableName + " :: Batch >> " + batch); 
        PerformInsert(tableName, tbl, counter); 
       } 

       tbl = null; 
       Console.WriteLine("BulkCopy Success!"); 
      } 
      catch (Exception) 
      { 
       Console.WriteLine("BulkCopy Fail!"); 
      } 
      finally 
      { 
       reader.Close(); 
       reader.Dispose(); 
      } 
      Console.WriteLine(tableName + " BulkCopy Ended."); 
     } 
    } 

UPDATE 私は私が行うことができ、その中にしばらくの内側(reader.Read())ループ認識していなかった第二の選択肢

のために行ってきました以下。大幅アプリはこれはあなたが後にしている答えではないかもしれないが、あなただけの1のtry文で、最初のリリースモードでコンソールアプリケーションを実行し、インデックスを使用してみましたが

while (reader.Read()) 
{ 
    object[] obj = tblRow.ItemArray; 
    reader.GetValues(obj); 
    tblRow.ItemArray = obj; 
    tbl.LoadDataRow(tblRow.ItemArray, true); 
} 

答えて

1

をパフォーマンス増加に貢献したI't読者に? SQL Serverが主要なボトルネックになるため、マルチスレッド化することでスピードを大幅に上げることはできません。

もちろん、データの整合性についてあまり気にしない場合(IDがシーケンシャルでないなど)、挿入のためにtable lockingタイプを変更し、3-4スレッドをスピンアップしてテーブルの特定のポイントから読み取ることができます。

+0

のようなものにforeachループを変換することができ、私はdefの注目点として、すべてのご提案をしてみてくださいよ、だろうあなたはC#からテーブルのロッキングタイプを変更する方法についてのコードサンプルを提供することができます。文字通り最初に私が今聞いたことは、ビットスペース時代です:p(私はgoogleよく) –

0

私はあなたのユースケースがそれぞれのために並行して大きく恩恵を受けるとは思いません。また、あなたのコードで使用されているOleDbReaderの原因を実装するのはかなり難しいでしょう。

しかし、SQL Serverでデータを挿入する必要があるときにループがブロックしない新しいスレッドに挿入をスケジュールすることができます。

これにはTask.Factory.StartNew()methodを使用できます。しかし、これによりエラー処理がより複雑になります。挿入が失敗した場合、より多くのデータを処理した可能性があります。最悪の場合、新しい挿入を待っているもう1つのスレッドがデータベースにあります。

4

初心者の間違いを解消するには、マルチスレッド化する必要はありません。どこでも低速コードのトン。

tblRow [col.Name] = reader [col.Name];

低。決して名前を使用しない - ループの外側でインデックスを取得し、インデックスを使用します。この行には、eery行の2つの(!)ディクショナリ・ルックアップがあり、行の処理よりも時間がかかります。

DataTables/DataSetは(悪いtrechnologicalの選択)で始まるのが遅すぎますが、そのようなコードは本当に遅いです。他の不良要素を見るには、プロファイラを使用します。

+0

インデックスがパフォーマンス上の利点を与えることはわかっていませんでしたが、私はそれが辛いことに気付いています。ありがとうございます。今すぐ試してみましょう...そして、データテーブルの場合、SqlBulkCopyはデータテーブル、データロード、データウェアハウス(私は使用できませんでした。コードはトランザクション全体が失敗する原因になります)、それは私の最初の選択肢でした... –

+1

最初に小さな最適化を並べ替えるために+1。 –

+0

で始まるシングルスレッドバージョンをもっと速く得ることができる場合は、マルチスレッドを使用する必要はないことがわかっているかもしれません。インデックスを使用するようにコードを更新しました。パフォーマンスはほぼ同じです。私は一回のパスで20 000レコードの一括挿入を行い、テーブルごとに+/- 5milレコードと60個の奇妙なテーブルを...私はネットワーク上のパフォーマンスを知っているので、驚くことはありません...それはなぜ私の心の中で方法は、複数のスレッドで発生するデータテーブルへのレコードの追加を持っていた...再び、データセットwas not私の最初の選択/ルート私が取った...バルク挿入は、行く方法のように思えたので、私はそれを取った仕事を完了してください... –

0

は、.NET 4を使用している場合は、TPLを使用してみてください、と

Parallel.ForEach(table.Columns, col => {/*rest of function here */} 
+0

悲しいことに、主要な問題は完全に無視されたままになります。あなたはその広告を無限にパラレル化することはできません。 – TomTom

関連する問題