none
大量データのUPDATEが非常に遅くなりました(パフォーマンスチューニングは可能か?) RRS feed

  • 質問

  • お世話さまです。

    SQL SERVER2012 Standard Edition (64-bit)を使用しております。

    86列からなるテーブルをUNIQUE CLUSTERED INDEXのみをキーにして

    18列の値を更新すべくUPDATEかけていたのですが、データ件数が約760万件の

    時には3時間弱で終わっていた更新処理が900万件に増えた途端、36時間弱

    もかかるようになってしまいました。

    また、同じテーブルの12列をUPDATEする処理は38分から16時間かかるように

    なってしまいました。

    ちなみに、このテーブルに張ってあるインデックスはこの1つのみでWHERE句でも

    このキーの値のみを検索条件にしています。

    ワークロードファイルを採取してデータベースエンジンチューニングアドバイザに

    かけても改善案は提示されませんでした。

    sp_spaceusedの結果は以下の通りです。

    database_name database_size unallocated space
    testdb  55000.00 MB 21460.08 MB

    reserved data  index_size unused
    29224880 KB 9004112 KB 20217536 KB 3232 KB

    インデックスのFILLFACTORを100から90に変えても

    改善されませんでした。

    パフォーマンスを改善する方策として何かありましたらご教示頂けると

    ありがたいのですが。

    以上、宜しくお願い致します。

    2014年5月8日 23:52

回答

  • 処理を2回に分けて行う(例えば500万件ごと)とかでは、駄目なのでしょうか?

    2014年5月9日 5:49
  • 1 トランザクション内で UPDATE 文を 900 万回実行しているのであれば、加速度的に遅くなるのが普通です。

    ボトルネックがどこか分からないので何とも言えませんが、加速度的に遅くなった状況から、保持しているロック数に依る問題の可能性がありそうです。
    もしそうであれば、最初にテーブルヒントを使ってテーブル全体に更新ロックをかけてから UPDATE 文を実行するように変えるだけでも早くなるかもしれません。

    あるいはUPDATE したい内容を一時テーブルに BULK INSERT などで格納して、UPDATE 文自体は 1 つで済ます、という手法もありそうです。
    Disk IO がボトルネックの場合によっては余計遅くなりますが・・・。

    以下は蛇足ですが、今回の場合は一連の処理開始直後と処理開始 1 時間経過時点で以下のクエリで取得できる結果が極端に異なるのではないですかね。
    SELECT COUNT(*)
    FROM sys.dm_tran_locks
    WHERE request_session_id = ?? --ここは適切な Session ID を設定する
    処理時間が加速度的に伸びた事象に関するパフォーマンス周りを調べるときは、処理開始直後と一定時間たってからの状況が大きく異なることがあるので、注意が必要です。
    CPU の使用率などは追われているようですが、これも開始直後と 1 時間経過時点など、複数時点で確認される方がお勧めです。
    サーバーのスペックに依る限界値を超えた所から劇的に遅くなる現象の場合に、ここを見落とすと判断を誤りやすくなります。


    MCITP(Database Developer/Database Administrator)

    2014年5月9日 7:15
  • aboveusonlysky さま よろしく。

    少し、気になりましたので、書き込みます。

    SQL Server の問題と言うより、フロントエンドとなる VB アプリのメモリーの問題ではないのでしょうか。

    1レコード毎に対応するUPDATE文を生成して > という点が気になります。

    文字列をハードコードで生成しているのか、その場合、StringBuilder クラスを使っているのでしょうか。
    更に、パラメータ化クエリ (@ 指定) には なっていないのでしょうか。
    その辺りを確認して見るといいのではないでしょうか。  推奨:パラメータ化クエリ
    2014年5月9日 7:41
  • そもそも、後であげられたテーブルのCreate文を見ますと、主キー13バイトで、1レコード500バイト程度ですね。
    これが10M件あるとして、INDEX:130MB、データ:5GB程度になる、とざっくり見積もれます。
    (まあ、クラスタ化インデクスは「タダ」ですが。)

    ここで、挙げられたsp_spaceusedの結果では、index_size:20GB、data:9GBで、
    データはともかく、インデクスが理不尽に大きいと感じます。

    本当に「このテーブルに張ってあるインデックスはこの1つのみ」なんでしょうか?

    あとは、Create Table文では、全フィールドNULL可能な感じなのも気になるところですが。


    jzkey

    2014年5月9日 12:51
  • パラメタライズドクエリに関しては、速度的な対応にはさほどならないと思います。
    ※もちろん、対応すべきである事は間違いありません。

    900万件のUPDATE文をどの様に発行しているのでしょうか?
    1.Loopしながら900万回発行
    2.LoopしながらSQL文をセミコロンで連結し、ある程度の件数をまとめて発行
      ※Loop件数 > SQL発行回数

    もし1の形式を取っているのであれば、2の形式に変更するだけで劇的に改善すると思います。

    2014年5月12日 0:30
  • アプリで色々やるよりは、素直にストアドで書き直した方が良いような・・・
    2014年5月12日 7:32
  • すいません、こんなやり方があるとは知りませんでした。

    これは下記のようなカンジで実装可能なのでしょうか?

    dim strsql as new StringBuilder

    strsql.Append("Update Tbl_Test Set Col01 = "XXX" Where Col02 = "X"; ")

    strsql.Append("Update Tbl_Test Set Col01 = "XXX" Where Col02 = "X"; ")

    Cmd.CommandText = strsql.ToString

    Cmd.ExecuteNonQuery

    この集約回数も多すぎたら余計遅くなるとかあるんでしょうね。

    一般的にはどれぐらいの更新を一度にまとめたらいいんでしょうか?

    実際に何パターンかやってみて高レスポンスの回数を定めるのでしょうか?

    以上、お手数をおかけしますがご教示のほど宜しくお願い致します。

    上記のイメージ通りです。

    余計遅くなるとかは基本的に有りませんが、一度に実行できるSQL文の長さの限界を超えるとシステムエラーになります。

    ※定かでは有りませんが数万字でエラーになったと記憶しています。

    2014年5月12日 8:21
  • クローズとの事でもう許容出来るレベルになった様ですが、
    SQLの発行回数を減らす対応は試されないでしょうか?
    ※コミット回数ではなく

    現時点のソースがわからないのではっきりは言えませんが、
    さほど大規模に作り直す事無く対応出来るかなぁと。

    ストアドやSQL CLRで作り直す事を除けば一番効果が大きいと思うのですが、、、

    2014年5月19日 1:16
  • スミマセン、気付いていませんでした。

    クエリの発行とコミットは全く別物なので、表現する際には気を付けて頂いた方が良いと思います。
    これ以外の方法を探る様にお伝えする物では有りません。

    ただ、50件ずつですか・・・
    実行可能な文字数をある程度調査して、その文字数を超える直前までまとめて発行するとかが私的には好みです。
    ※発行回数は極力減らしたいので。

    こんな感じ

    Const MAX_LENGTH As Integer = 50000
    Dim sb As New StringBuilder
    For Each item as Entity in list
    	Dim sql As New StringBuilder
    	'SQL文を生成
    	ゴニョゴニョ
    	If sb.Length + sql.Length > MAX_LENGTH Then
    		'クエリ発行
    		ゴニョゴニョ
    		'クエリ変数クリア
    		sb.Clear()
    	End If
    	sb.Append(sql.ToString())
    Next
    If sb.Length > 0 Then
    	'クエリ発行
    	ゴニョゴニョ
    End If
    
    今更間全開ですが・・・
    2014年6月4日 9:25

すべての返信

  • 何点か補足致します。

    当該データベースの復旧モデルはログからの復旧の必要がないため、単純にしてあります。

    実際の処理は下記の3段階に分かれています。

    STEP1

    900万件のインポート用CSVファイルを元にテーブルを新規に追加してCREATE INDEXする。(30分弱で終了)

    この直後にsp_updatestatsで統計情報を更新し、DBCC SHRINKDATABASEで圧縮をかけています。

    STEP2

    900万件のトランザクションデータを上記テーブルと主キーでマッチングして

    18列の値を更新する。(これが36時間かかる)

    STEP3

    900万件のトランザクションデータを上記テーブルと主キーでマッチングして

    12列の値を更新する。(これが16時間かかる)

    以上です。

    2014年5月9日 0:16
  • 何点か補足致します。

    当該データベースの復旧モデルはログからの復旧の必要がないため、単純にしてあります。

    実際の処理は下記の3段階に分かれています。

    STEP1

    900万件のインポート用CSVファイルを元にテーブルを新規に追加してCREATE INDEXする。(30分弱で終了)

    この直後にsp_updatestatsで統計情報を更新し、DBCC SHRINKDATABASEで圧縮をかけています。

    STEP2

    900万件のトランザクションデータを上記テーブルと主キーでマッチングして

    18列の値を更新する。(これが36時間かかる)

    STEP3

    900万件のトランザクションデータを上記テーブルと主キーでマッチングして

    12列の値を更新する。(これが16時間かかる)

    以上です。

    ここで言う所のSTEP2とSTEP3はUPDATE文を発行するかと思いますが、このUPDATE文を含む処理内容をある程度提示出来ますか?

    ※テーブル名やカラム名等は適当な値に変更して構いませんので。

    • 回答としてマーク aboveusonlysky 2014年5月19日 1:01
    • 回答としてマークされていない aboveusonlysky 2014年5月19日 1:06
    2014年5月9日 1:12
  • ===>aviator__様

    早速のレス、ありがとうございます。

    SQL文は以下のようなものです。

    UPDATE TBL_TEST

    SET COL02 = 'XXXXXXXXXXXXX',

    COL03 = 'XXXXXXXXXXXXXXXX',

    COL04 = '4',

    COL20 = 9999,

    COL21 = '10',

    COL22 = '2005/07/25',

    COL23 = '2013/11/17',

    COL25 = 'NNNNNNNNNNNNNN',

    COL26 = NULL,

    COL27 = '2009/12/21',

    COL28 = 9999,

    COL29 = '10',

    COL30 = NULL,

    COL31 = NULL,

    COL32 = NULL,

    COL33 = '20',

    COL34 = '#',

    COL36 = '#'

    WHERE COL01 = 'XXXXXXXXXXXXX'

    ※COL25にセットしているのは倍角漢字


    ちなみに、本テーブルのCREATE文は以下になります。

    CREATE TABLE TBL_TEST   (
         COL01 char ( 13 ),
         COL02 char ( 13 ),
         COL03 char ( 16 ),
         COL04 char ( 1 ),
         COL05 char ( 10 ),
         COL06 char ( 1 ),
         COL07 char ( 10 ),
         COL08 tinyint,
         COL09 char ( 2 ),
         COL10 char ( 2 ),
         COL11 char ( 2 ),
         COL12 char ( 2 ),
         COL13 char ( 2 ),
         COL14 char ( 2 ),
         COL15 char ( 2 ),
         COL16 char ( 1 ),
         COL17 char ( 1 ),
         COL18 char ( 1 ),
         COL19 char ( 10 ),
         COL20 int,
         COL21 char ( 2 ),
         COL22 char ( 10 ),
         COL23 char ( 10 ),
         COL24 varchar ( 100 ),
         COL25 varchar ( 100 ),
         COL26 char ( 10 ),
         COL27 int,
         COL28 char ( 2 ),
         COL29 char ( 10 ),
         COL30 char ( 10 ),
         COL31 char ( 10 ),
         COL32 char ( 2 ),
         COL33 char ( 1 ),
         COL34 char ( 1 ),
         COL35 char ( 1 ),
         COL36 char ( 1 ),
         COL37 char ( 1 ),
         COL38 char ( 1 ),
         COL39 char ( 1 ),
         COL40 char ( 1 ),
         COL41 char ( 1 ),
         COL42 char ( 1 ),
         COL43 char( 1 ),
         COL44 char( 1 ),
         COL45 int,
         COL46 char ( 2 ),
         COL47 int,
         COL48 char ( 2 ),
         COL49 int,
         COL50 int,
         COL51 int,
         COL52 int,
         COL53 int,
         COL54 int,
         COL55 int,
         COL56 int,
         COL57 int,
         COL58 int,
         COL59 char ( 2 ),
         COL60 char ( 2 ),
         COL61 char ( 2 ),
         COL62 char ( 2 ),
         COL63 char ( 2 ),
         COL64 char ( 2 ),
         COL65 char ( 2 ),
         COL66 char ( 2 ),
         COL67 char ( 2 ),
         COL68 char ( 2 ),
         COL69 int,
         COL70 char ( 2 ),
         COL71 int,
         COL72 char ( 2 ),
         COL73 int,
         COL74 char ( 2 ),
         COL75 char ( 1 ),
         COL76 char ( 1 ),
         COL77 char ( 1 ),
         COL78 char ( 1 ),
         COL79 char ( 1 ),
         COL80 char ( 1 ),
         COL81 char ( 1 ),
         COL82 char ( 1 ),
         COL83 char ( 1 ),
         COL84 char ( 1 ),
         COL85 char ( 1 ),
         COL86 char ( 1 )
     )

    以上、宜しくお願い致します。


    2014年5月9日 2:18
  • 更に実行環境について補足します。

    当更新ジョブはVB.NET2010で作成したアプリで行っており

    サーバーOSはWindows 2008 R2で40GBのメモリを積んだサーバーの

    仮想ゲストサーバー上で実行しています。

    当ゲストサーバーには20GBのメモリを割り当ています。

    パフォーマンスモニタを見るとCPUの負荷は低位に推移しており

    メモリは最終的には20GBフルに消費しています。

    VBでの処理は更新用トランザクションファイル(900万件)のCSVを読み込んで

    1レコード毎に対応するUPDATE文を生成して先述したSQL文をExecuteしています。

    以上です。

    2014年5月9日 3:29
  • 処理を2回に分けて行う(例えば500万件ごと)とかでは、駄目なのでしょうか?

    2014年5月9日 5:49
  • ===>藤森幸治様

    早速のレスありがとうございます。

    分割処理は可能です。

    その手があったか!?と目からウロコ状態です。

    決定打的な解決策が見つからなかった場合には採用しようと思います。

    ありがとうございました。

    解決策とは別に、総データ件数は900万件と多いものの増分としてはたかだか18%程度増えた

    だけでなぜに処理時間が12倍にも膨れ上がってしまうのか、という素朴な疑問が残ります。

    限界値的な何かの問題なんでしょうか。

    2014年5月9日 6:15
  • 1 トランザクション内で UPDATE 文を 900 万回実行しているのであれば、加速度的に遅くなるのが普通です。

    ボトルネックがどこか分からないので何とも言えませんが、加速度的に遅くなった状況から、保持しているロック数に依る問題の可能性がありそうです。
    もしそうであれば、最初にテーブルヒントを使ってテーブル全体に更新ロックをかけてから UPDATE 文を実行するように変えるだけでも早くなるかもしれません。

    あるいはUPDATE したい内容を一時テーブルに BULK INSERT などで格納して、UPDATE 文自体は 1 つで済ます、という手法もありそうです。
    Disk IO がボトルネックの場合によっては余計遅くなりますが・・・。

    以下は蛇足ですが、今回の場合は一連の処理開始直後と処理開始 1 時間経過時点で以下のクエリで取得できる結果が極端に異なるのではないですかね。
    SELECT COUNT(*)
    FROM sys.dm_tran_locks
    WHERE request_session_id = ?? --ここは適切な Session ID を設定する
    処理時間が加速度的に伸びた事象に関するパフォーマンス周りを調べるときは、処理開始直後と一定時間たってからの状況が大きく異なることがあるので、注意が必要です。
    CPU の使用率などは追われているようですが、これも開始直後と 1 時間経過時点など、複数時点で確認される方がお勧めです。
    サーバーのスペックに依る限界値を超えた所から劇的に遅くなる現象の場合に、ここを見落とすと判断を誤りやすくなります。


    MCITP(Database Developer/Database Administrator)

    2014年5月9日 7:15
  • aboveusonlysky さま よろしく。

    少し、気になりましたので、書き込みます。

    SQL Server の問題と言うより、フロントエンドとなる VB アプリのメモリーの問題ではないのでしょうか。

    1レコード毎に対応するUPDATE文を生成して > という点が気になります。

    文字列をハードコードで生成しているのか、その場合、StringBuilder クラスを使っているのでしょうか。
    更に、パラメータ化クエリ (@ 指定) には なっていないのでしょうか。
    その辺りを確認して見るといいのではないでしょうか。  推奨:パラメータ化クエリ
    2014年5月9日 7:41
  • ===>nagino様

    様々なヒントをありがとうございました。

    ロックの観点も完全に欠落しておりました。

    また、tempテーブルを使った更新テクニックも考えもつきませんでした。

    まずはロックについて実装してみたいと思います。

    本当にありがとうございました!

    2014年5月9日 8:07
  • ===>ShiroYuki_Mot様

    レス、ありがとうございました。

    VB内でのSQL文の生成にはStringBuilderクラスを使っています。

    更新列は変わらないのでご指摘のようにパラメータ化クエリが有効ですね。

    これも頭から抜けてました。

    パラメータクエリも実装してみたいと思います。

    本当にありがとうございました。

    2014年5月9日 8:22
  • そもそも、後であげられたテーブルのCreate文を見ますと、主キー13バイトで、1レコード500バイト程度ですね。
    これが10M件あるとして、INDEX:130MB、データ:5GB程度になる、とざっくり見積もれます。
    (まあ、クラスタ化インデクスは「タダ」ですが。)

    ここで、挙げられたsp_spaceusedの結果では、index_size:20GB、data:9GBで、
    データはともかく、インデクスが理不尽に大きいと感じます。

    本当に「このテーブルに張ってあるインデックスはこの1つのみ」なんでしょうか?

    あとは、Create Table文では、全フィールドNULL可能な感じなのも気になるところですが。


    jzkey

    2014年5月9日 12:51
  • ===>jzkey様

    お世話さまです。

    レスありがとうございました。

    >本当に「このテーブルに張ってあるインデックスはこの1つのみ」なんでしょうか?

    実はこのテーブルにはClusterd Indexの他に集計用に7つのインデックスを

    張ってあったのですが、それが遅さの原因かもしれないと思い、それら7つを全てDrop Index

    して主キーのみにしてから更新した結果がこのありさまでした。

    また、当Testdbには1億件以上のデータを擁する他のテーブルが存在するため

    インデックス領域は大きくなっているのだと思います。

    当該テーブルがマスタで、これに紐づく明細的テーブルが何種類か存在し

    それら明細テーブルの件数は数千万件や1億件以上のレコードを持つものが存在します。

    2014年5月11日 23:42
  • パラメタライズドクエリに関しては、速度的な対応にはさほどならないと思います。
    ※もちろん、対応すべきである事は間違いありません。

    900万件のUPDATE文をどの様に発行しているのでしょうか?
    1.Loopしながら900万回発行
    2.LoopしながらSQL文をセミコロンで連結し、ある程度の件数をまとめて発行
      ※Loop件数 > SQL発行回数

    もし1の形式を取っているのであれば、2の形式に変更するだけで劇的に改善すると思います。

    2014年5月12日 0:30
  • ===>aviator

    レスありがとうございます。

    パラメタライズドクエリに関しては、速度的な対応にはさほどならないと思います。

    プレコンパイルすることで逐次実行よりも速度が速くなるとされるストアドプロシージャでも

    逐次実行より遅くなった経験があり、うっすらとそんな予感もしております。(笑)

    2.LoopしながらSQL文をセミコロンで連結し、ある程度の件数をまとめて発行

    すいません、こんなやり方があるとは知りませんでした。

    これは下記のようなカンジで実装可能なのでしょうか?

    dim strsql as new StringBuilder

    strsql.Append("Update Tbl_Test Set Col01 = "XXX" Where Col02 = "X"; ")

    strsql.Append("Update Tbl_Test Set Col01 = "XXX" Where Col02 = "X"; ")

    Cmd.CommandText = strsql.ToString

    Cmd.ExecuteNonQuery

    この集約回数も多すぎたら余計遅くなるとかあるんでしょうね。

    一般的にはどれぐらいの更新を一度にまとめたらいいんでしょうか?

    実際に何パターンかやってみて高レスポンスの回数を定めるのでしょうか?

    以上、お手数をおかけしますがご教示のほど宜しくお願い致します。

    2014年5月12日 5:30
  • アプリで色々やるよりは、素直にストアドで書き直した方が良いような・・・
    2014年5月12日 7:32
  • ===>藤森幸治

    お世話さまです。

    ストアドで書き直すというのは、複数のUPDATE文が実行可能なパラメータ化クエリを

    作成して実行するということでしょうか?

    自分は比較的単純なストアドしか作ったことがありませんので、どのような

    SQL文で実装できるのか皆目見当もつきません。^^;

    2014年5月12日 8:07
  • すいません、こんなやり方があるとは知りませんでした。

    これは下記のようなカンジで実装可能なのでしょうか?

    dim strsql as new StringBuilder

    strsql.Append("Update Tbl_Test Set Col01 = "XXX" Where Col02 = "X"; ")

    strsql.Append("Update Tbl_Test Set Col01 = "XXX" Where Col02 = "X"; ")

    Cmd.CommandText = strsql.ToString

    Cmd.ExecuteNonQuery

    この集約回数も多すぎたら余計遅くなるとかあるんでしょうね。

    一般的にはどれぐらいの更新を一度にまとめたらいいんでしょうか?

    実際に何パターンかやってみて高レスポンスの回数を定めるのでしょうか?

    以上、お手数をおかけしますがご教示のほど宜しくお願い致します。

    上記のイメージ通りです。

    余計遅くなるとかは基本的に有りませんが、一度に実行できるSQL文の長さの限界を超えるとシステムエラーになります。

    ※定かでは有りませんが数万字でエラーになったと記憶しています。

    2014年5月12日 8:21
  • ===>aviator

    レスありがとうございます。

    余計遅くなるとかは基本的に有りませんが、一度に実行できるSQL文の長さの限界を超えるとシステムエラーになります。

    とりあえずその限界点のみ考慮して実装してみます。

    皆様からたくさんのアドバイスを頂き感謝です。

    これから1つづつ試して効果のほどを検証してみたいと思います。

    検証結果はここにフィードバックするツモリです。

    ただ、UPには他の仕事との兼ね合いもあり数週間かかるやもしれません。

    2014年5月12日 8:42
  • お世話さまです。

    一部の検証結果をUPします。

    900万件で何度もテストするのは日数的に厳しかったので、10万件をランダム抽出した

    テーブルを別途作成して更新を掛けました。

    改修前の更新プログラムでは16時間かかったSTEP2をテストしました。

    10万件で更新した結果、10分52秒で終了しました。

    まず、テーブルロックについてですが、下記のようにUPDATE文にTABLOCKを追加して実行してみました。

    UPDATE TBL_TEST WITH(TABLOCK)

    SET COL02 = 'XXXXXXXXXXXXX',

    が、レスポンスに改善は見られませんでした。

    そもそも、毎回のUPDATE文にTABLOCKを使うのが正しいのかどうかも分かりませんし

    明示的に指定しなくてもエスカレーションで最適化されているんじゃないでしょうか?

    次に、複数のUPDATE文を数回分まとめてコミットする方法をテストしました。

    条件を合わせるために、テスト前にサーバーを再起動し、その直後に実行した結果です。

    ※()内の数字は集約回数、つまり(1)は逐次実行です。

    (1)
    Elapsed Time = 10:50

    (10)
    Elapsed Time = 10:55

    (50)
    Elapsed Time = 10:35

    (100)
    Elapsed Time = 10:52

    (200)
    Elapsed Time = 11:12

    (500)
    Elapsed Time = 10:48

    CPU時間ではなく、経過時間なので厳密な比較にはならないかもしれませんが

    当該サーバーはこの更新ジョブでのみ使用しており、比較実行条件はほぼ同じだと思います。

    ということで、期待したほどの差異は見られませんでした。

    一番速かった50回分を集約した形で900万件の更新をやってみようとは思います。

    次回は、パラメータ化クエリでのテスト結果をUPしようと思います。

    ところで、パラメータ化クエリもSQL文内で集約可能なのでしょうか?


    2014年5月15日 7:51
  • お世話さまです。

    900万件で1回のコミットで50個のUPDATE文を実行したところ、16時間かかっていた

    のが13時間半に短縮できました。^^;

    まずはご報告まで。

    2014年5月16日 1:20
  • お世話さまです。

    900万件で36時間かかっていた処理を、パラメータ化クエリにするとともに

    当該クエリを50回に1回コミットする形に変更して実行した結果、27時間48分まで短縮できました。

    現状の1テーブルでの処理ではこれが限界のような気がします。

    これ以上速くするには、テーブル分割しかないと考えております。

    レスを頂いた皆様には様々なヒントを頂き、誠に感謝しております。

    今後とも宜しくお願い致します。

    これにて、当スレッドはクローズとさせて頂きます。

    本当にありがとうございました。

    2014年5月19日 1:01
  • クローズとの事でもう許容出来るレベルになった様ですが、
    SQLの発行回数を減らす対応は試されないでしょうか?
    ※コミット回数ではなく

    現時点のソースがわからないのではっきりは言えませんが、
    さほど大規模に作り直す事無く対応出来るかなぁと。

    ストアドやSQL CLRで作り直す事を除けば一番効果が大きいと思うのですが、、、

    2014年5月19日 1:16
  • ===>aviator

    レスありがとうございます。

    すいません、私がコミットの回数を減らしたと表現しているのは

    50個のUPDATE文をセミコロンで連結して一度のExecuteNonQueryで実行していること

    なのですが、これではない方法でまだ何かしらやれることなのでしょうか?

    お忙しいところお手数をおかけしますが、ご教示頂けるとありがたいです。

    2014年5月19日 5:31
  • スミマセン、気付いていませんでした。

    クエリの発行とコミットは全く別物なので、表現する際には気を付けて頂いた方が良いと思います。
    これ以外の方法を探る様にお伝えする物では有りません。

    ただ、50件ずつですか・・・
    実行可能な文字数をある程度調査して、その文字数を超える直前までまとめて発行するとかが私的には好みです。
    ※発行回数は極力減らしたいので。

    こんな感じ

    Const MAX_LENGTH As Integer = 50000
    Dim sb As New StringBuilder
    For Each item as Entity in list
    	Dim sql As New StringBuilder
    	'SQL文を生成
    	ゴニョゴニョ
    	If sb.Length + sql.Length > MAX_LENGTH Then
    		'クエリ発行
    		ゴニョゴニョ
    		'クエリ変数クリア
    		sb.Clear()
    	End If
    	sb.Append(sql.ToString())
    Next
    If sb.Length > 0 Then
    	'クエリ発行
    	ゴニョゴニョ
    End If
    
    今更間全開ですが・・・
    2014年6月4日 9:25
  • ===>aviator様

    お世話さまです。

    レスありがとうございました。

    >クエリの発行とコミットは全く別物なので、表現する際には気を付けて頂いた方が良いと思います。

    承知しました。

    ご教示頂いたように文字数をトリガーにした方がスマートですね。

    件数で制限をかけると思いがけず長いSQL文になったとこにコケる可能性もありますので。

    ありがとうございました。

    2014年6月6日 2:11