0

私は30個のファイルのセットを持っています。これらのファイルをループし、それぞれに約 30 列の 1529 行と、約 6 列の 219487 行を挿入します。

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

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

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

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

バッチサイズを 20000 に減らしましたが、違いはありませんでした。過去に私はそれを 5000 と 10000 に減らしたと思いますが、それでも違いはありませんでした。基礎となる SQL アーキテクチャについてあまり知らないので、少し迷っています。

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

バッチ サイズを 100 に減らしました (サーバーが過負荷にならないようにするため)。

全体を通して、ファイルごとの SQL 時間と CPU 時間の合計ではなく、SQL 挿入にかかった時間を参照してきました。

何が起こっているのか正確にアドバイスすることはおそらく不可能でしょうが、これを最善の方法で修正するために絶対に避けるべきヒントや事柄を教えてもらえますか?

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

2 に答える 2

0

SQLサーバーに過負荷をかけているように感じます

はい、それは正当な理由です。特に、SQL サーバーが携帯電話で実行されているか、哀れなエンド ユーザー ディスクを持っている場合に限ります。そうでなければ - いいえ。

基礎となる SQL アーキテクチャについてあまり知らないので、少し迷っています。

探し出す。クエリ プランを取得します。テーブル + インデックスが必要です。ユニーク制約?インデックスなしの一意の制約はありますか? これにより、常にテーブルスキャンが強制されます。

また価値があります:元のテーブルから作成した一時テーブルに挿入し(簡単)、1つのステートメントでデータをコピーします。

最初のファイルで 9 秒から

すでに十分な220.000行の場合。ポエレーション中のサーバーのビジー状態と、インデックスを一致させるためのテーブルのすべての制約を確認することをお勧めします。そしてトリガー;)

于 2012-05-02T11:33:14.933 に答える
0

これにはいくつもの可能性がありますが、私にとって明白なものは次のとおりです。

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

これらはすべて、私が以前に経験した問題です。それらのいずれかまたは任意の組み合わせにより、説明している症状が発生する可能性があります。

于 2012-05-02T11:34:46.693 に答える