2012-05-02 24 views
0

私は30ファイルのセットを持っています。私はこれらのファイルをループし、それぞれについて約30列、およそ6列を含む219487行を挿入する1529行を挿入します。SQLサーバーのパフォーマンスが低下する理由は何ですか?

私はこれをC#で行い、データテーブル(下を参照)を使用して挿入します。私は、1529行(30列)のバッチごとに1,300行と219,487行(6列)のバッチごとに50000にグループ化しました。

各バッチを挿入するときには、マルチスレッド化はありません。すべてが(少なくとも私のコードでは)シーケンシャルです。私のコード行が前のファイルの挿入を完了するまで、次のファイルを開始しません。

これを念頭に置いて、私はSQLサーバーが一定の時間内に各ファイルを完成することを期待しています(ファイルは非常に似ていますが、常に1529と219487の挿入です)。

ただし、ファイルごとの各SQL挿入に要する時間は、最初のファイルの9秒から30番目のファイルの50秒に直線的に増加します。私は取ったSQL時間からCPU時間を分けており、最初は6列の行の1つを挿入するのに0.000033秒かかっています。最後に、後のファイルの場合、6列のデータの場合は、0.000228になります。つまり、219,487行(6列)のデータを挿入するのにかかる時間が約7倍になりましたか?

バッチサイズを20000に減らしても差はありませんでした。過去に私はそれを5000と10000に減らしたと信じていましたが、それはまだ何の違いもありませんでした。基本的なSQLアーキテクチャについてはあまりよく分かりませんので、少し失われています。

私はSQLサーバーに過負荷を感じています。しかし、これはSQLサーバーにジョブを渡すのではなく、順次実行されているという印象の下にあったのでしょうか? SQLリクエストがスレッドによって生成される可能性はありますが、バッチサイズを100に減らしています(さらに下を参照)。これはまだ助けにはなりません。完了までの全体の時間は長くなりましたが、それでもファイルごとに直線的に増加しました。

私はバッチサイズを100に減らしました(サーバーが過負荷にならないようにするため)、私はまだ直線的に増加する時間を見ていますか?

私はSQLの挿入に要した時間を指していましたが、1ファイルあたりのSQL + CPU時間の合計ではありません。

何が起こっているのか正確にアドバイスすることは不可能でしょうが、これを修正する可能性があることを間違いなく避けるためのヒントやものがありますか?

(各バッチ挿入ごとに呼ばれる)マイSQL挿入コードは次のとおりです。

private static void WriteResultsToDatabase(string tableName, DataTable tableToWrite) 
     { 

      using (SqlConnection connection = 
        new SqlConnection(connectionString)) 
      { 
       SqlBulkCopy bulkCopy = 
        new SqlBulkCopy 
        (
        connection, 
        SqlBulkCopyOptions.TableLock | 
        SqlBulkCopyOptions.FireTriggers | 
        SqlBulkCopyOptions.UseInternalTransaction, 
        null 
        ); 

       bulkCopy.DestinationTableName = tableName; 
       for (int i = 0; i < tableToWrite.Columns.Count; i++) 
        bulkCopy.ColumnMappings.Add(tableToWrite.Columns[i].ColumnName, tableToWrite.Columns[i].ColumnName); 
       try 
       { 
        connection.Open(); 

        bulkCopy.WriteToServer(tableToWrite); 

       } 
       finally 
       { 
        connection.Close(); 
       } 
      } 
     } 

答えて

0

それは私がはい、それは正当な理由であるSQLサーバー

をオーバーロードしていますように私には感じています特にあなたのSQLサーバが携帯電話で動作しているか、哀れなエンドユーザディスクを持っている場合に限ります。そうでなければ - いいえ。

基本的なSQLアーキテクチャについてはあまりよく分かりませんが、少し失われています。

クエリプランを取得します。テーブル+インデックスが必要です。ユニークな制約?インデックスを持たないユニークな制約はありますか?これは常にテーブルスキャンを強制します。

また価値があります:元のテーブルから作成した一時テーブルに挿入し(簡単)、1つのステートメントでデータをコピーします。すでにたくさんある220.000行の最初のファイル

で9秒から

。私はあなたの詩の中でどのくらいビジーであるか、そしてインデックスを一致させるためにテーブル上のすべての制約をサーバーにチェックすることをお勧めします。そして、トリガー、次のようにこれは私に物事の任意の数が、明らかなものかもしれない)

+0

単純なinsert文のクエリプランを取得しますか? – mezamorphic

+0

実際には、しかし、実行された計画にトリガが現れた場合、そのことが分かります。それは簡単な挿入のように見えるかもしれませんが、処理のトンをトリガします。 – TomTom

+0

私がSQLアーキテクチャを教えたとき、私はSQLがどのように特定のクエリプランではないのかということを意味しました:) – mezamorphic

0

は次のようになります。

  1. あなたは、テーブル上のクラスタ化キーを持っている、とあなたは レコードを挿入されていませんそのキーの順番で。すべての挿入操作に対して、 タスクを完了する前に、レコードを物理的に並べ替える必要があります。
  2. テーブルのチェックを含む複数のインデックス/外部キーがありますので、すべての繰り返しで、より多くの情報を に追加しています。
  3. トリガーが効率的に使用されていないか、最近挿入されたデータの代わりに テーブル全体に対して作業する必要があるという点で、 が効率的に構築されていません。
  4. バルクトランザクションを設定しましたが、 データベースサーバーがそのようなトランザクションを処理できないものがあります。アクティビティ モニタでこれがバルク操作と認識されていることを確認してください。
  5. 固定量の の代わりに、データベースをパーセンテージで自動的に増やしています。それぞれの成長のために、より多くのスペースを割り当てることに時間がかかります スペース。

これらは私が以前経験したすべての問題です。それらのいずれか1つまたは組み合わせによって、あなたが記述している症状を引き起こす可能性があります。

関連する問題