6

現在、プログラミングによって生成されたこのタイプのクエリを取得しました(c#)

INSERT INTO TableName (Field1, Field2, Field3)
SELECT Field1, Field2, Field3 FROM TableName2

問題は、SELECTが多数のレコード(100万など)の結果をもたらす可能性があるため、何度も時間がかかり、結果として接続タイムアウトが発生することです。

また、すべての挿入を1つの挿入に分割すると(この例では、100万の挿入クエリ)、実行に非常に長い時間がかかります...しかし、それは機能します...

このタイプのクエリを改善する方法はありますか?

私はMSSQl2005を使用しています

どうも

4

10 に答える 10

8

順番に実行される INSERT ステートメントが多数ある場合、 xxxx 個の INSERT ステートメントの後に 'GO' ステートメントを追加することでパフォーマンスを向上できることがわかりました。

...
INSERT INTO Table ( ... ) VALUES ( ... )
INSERT INTO Table ( ... ) VALUES ( ... )
INSERT INTO Table ( ... ) VALUES ( ... )
GO
INSERT INTO Table ( ... ) VALUES ( ... )
INSERT INTO Table ( ... ) VALUES ( ... )
...

別の可能性としては、 INSERT INTO .. SELECT FROM クエリが一度にすべてを挿入しないようにすることです。代わりに、何らかのページング手法を使用します。

INSERT INTO Table ...
SELECT ...
FROM OtherTable WHERE Id > x and Id < y
于 2009-02-12T15:10:24.627 に答える
6

うーん、フルコピーなら一括読み込みツールとか調べなくてもいいかな?

  • 一括挿入 (TSQL)
  • SqlBulkCopy (.NET)
  • bcp (コマンドライン)

句がある場合Where、適切にインデックスが作成されていることを確認します...

さらに:

  • おそらく、INSERT を実行する前にインデックスとトリガーを削除します (後で再作成します)。
  • テーブル全体を削除して SELECT INTO を使用することを検討してください。(コメントを参照)
于 2009-02-12T15:08:54.737 に答える
3

わかりました、いくつかの基本的な問題があります。

  1. I\O - テーブルが別のディスク上にない場合、別のテーブルから読み取り中にテーブルに挿入すると、ディスクの競合が発生する可能性が高くなります。反対側のテーブルを物理的に異なるスピンドルに配置します。

  2. トランザクション ログ - トランザクション ログが独自のディスク上にあることを確認するか、小さなトランザクション (一度に数千行) で作業するか、ログに記録されない BCP\Bulk Insert を使用する必要があります。

  3. クラスター化されたインデックス - これらの行をすべてターゲット テーブルに挿入し、そのクラスター化されたインデックス (物理的な順序のデータがディスクに書き込まれる) が順次に書き込まれない場合、ディスク IO 要件は、ページ分割と再割り当て。シーケンシャル シード キーであるクラスター化インデックスを受信者テーブルに作成することで、簡単に修正できます。これにより、通常、テーブルへの順次書き込みが確実に行われ、ほとんどの場合最後に行われます。

  4. ファイル拡張 - 10% 程度の適切な速度でファイルを拡張するように SQL が設定されていることを確認します。そうしないと、常にファイルのサイズを変更し、ディスクをゼロにする必要があります。Sql Service ユーザーのグループ ポリシーで一括ファイル操作のアクセス許可を有効にするなど、ディスクをゼロにする必要がないようにする方法もあります。

率直に言って、それと他のいくつかの提案を除けば、トランザクションで数百万行の挿入を本当に高速にすることはほとんどありません。Bulk Insert を介してこれを行うと、大幅に高速になりますが、アプリケーションの観点からは必要ないかもしれません。

于 2009-02-12T19:07:25.833 に答える
2

CommandTimeout使用しているのプロパティをSqlCommand適切な値 (10 分程度) に設定します。CommandTimeout秒単位であることを忘れないでください。

于 2009-02-12T15:09:15.470 に答える
1

ここにいくつかの良い答えがあります。

追加するのと同じように、宛先テーブルにインデックスがある場合、操作が遅くなります。ただし、ドロップ作成手法を実行すると、インデックスの再構築に時間がかかる場合があります。

インデックスを削除したくない場合は、宛先のクラスター化インデックスに一致するを使用しORDER BYてください。これは役立つようです(おそらくページ分割を最小限に抑えるのに役立ちます)。SELECT

于 2009-02-12T16:31:42.450 に答える
0

過去に使用したもう1つの方法は、移動してwhileループで使用する主キーを使用して一時テーブルを作成することです。このようにして、一種のブロック方式でそれを行うことができるので、キャンセルしてロールバックしなければならなかった場合の大きなトランザクションオーバーヘッドを回避できます。

基本的に、最終的に行うのは、テーブル名への挿入(...)select(...)from table name where primary key in(select top 10000 key from temptable)

セカンダリ結果セットに必要な上位10000は、一時テーブルから削除して、再度処理されないようにすることができます。

さらに別の方法は、カーソルを使用して、一度に処理するレコードの数を減らすことです。

もう1つのループ方法は、whileループでこのようなことを行うことです。

@stopをintとして宣言しますset@stop=(select count(primaryKey)from tableName where primaryKey not in destinstiontable)

while(@stop> 0)トランザクションを開始します

destinationTableに挿入(...)select(...)from sourcetable where primaryKey not in(select primarykey from destinationtable)

専念

set @stop =(select count(primaryKey)from tableName where primaryKey not in destinstiontable)end

最も効率的ではありませんが、機能し、トランザクションログを記録し続けることができるはずです。必要な場合を除いて、no lockキーワードを使用して、この大規模な移動を行うときに他のトランザクションをブロックしないようにしてください(BCPまたはDTSを使用すると、はるかに高速になります)。

言われていることのいくつかはおそらくあなたの最善の策です。BCP、DTS、またはその他のバルクツールを使用します。インデックスを削除できれば、処理が大幅に高速化されます。

于 2009-02-12T16:26:29.497 に答える
0

実際にかかる時間を確認するために、SQL Server Management Studio を使用して SQL をテストしましたか? 私はそこから始めます。選択のパフォーマンスを向上させることができます。また、挿入先のテーブルでタブロック ヒントを使用すると、パフォーマンスを改善できる場合があります。

于 2009-02-12T19:19:55.320 に答える
0

このアプローチで解決する問題を示していません。明らかに、WHERE はレコード セットを絞り込みます。しかし、結果セットが新しいテーブルで変更されないのであれば、なぜデータをレプリケートする必要があるのでしょうか? ソースから直接クエリを実行しないのはなぜですか?

于 2009-02-12T15:11:31.457 に答える
0

ファイルを使用して一括ロードしてから bcp/BULK INSERT をロードするか、5K 程度のバッチでバッチ処理します。

于 2009-02-12T15:11:52.233 に答える
0

そもそも、C# を使用して 100 万件のレコードを挿入しようとしないでください。レコードの大規模なグループを一度に 1 つずつ処理しないでください。これは、データベースがデータベースで行う必要がある作業です。これを行うには、一括挿入または SSIS または DTS を使用します。そして、それを時間外のジョブとしてスケジュールします。それでも時間がかかりすぎる場合は、数千のバッチで実行することをお勧めします (安全に処理できる数は、テーブル、インデックスの作成方法に大きく依存するため、最適な選択を確認するには、独自のデータベースを試してみる必要があります)。サーバーの速度と、同じテーブルに対して作業を行おうとしているユーザーの数。

于 2009-02-12T15:13:39.140 に答える