QA@IT
この質問・回答は、@ITの旧掲示板からインポートされたものです。

SqlException,タイムアウトに達しました・・・・

こんにちは。

以下のエラーで大変困っております。

SqlException,タイムアウトに達しました。
操作が完了する前にタイムアウト期間が過ぎたか、またはサーバーが応答していません。

内容は単純なDELETE文の実行です。

Private m_cn As SqlConnection
Private m_cm As SqlCommand
Private m_trn As SqlTransaction
Private m_strSQL As String

m_strSQL = ""
m_strSQL += "DELETE"
m_strSQL += " FROM テーブル名"
m_strSQL += " WHERE 条件"

'DB接続
m_cn = New SqlConnection
m_cn.ConnectionString = c_DbConstr & _
c_DbUser & _
c_DbPasswordm_strDbPassword)
m_cn.Open()

'コマンドオブジェクトの生成
m_cm = m_cn.CreateCommand()

'トランザクションの開始
m_tran = m_cn.BeginTransaction(IsolationLevel.ReadCommitted)
m_cm.Transaction = m_trn

'SQLステートメントの作成
m_cm.CommandText = m_strSQL

'実行
m_cm.ExecuteNonQuery()

'コミット
m_trn.Commit()
blnTran = True

扱うデータの件数を増やしテストをしています。
1万件、5万件、10万件、50万件

10万件までのテストはできるのに、
50万件のテストで上記のエラーが発生します。
直接SQL文を実行した場合は、エラーが発生しません。

言語 VB.NET
EXEファイル+クラスファイル(SQL文発行)
  
DB  SQLServer2000

よろしくお願いします。

[ メッセージ編集済み 編集者: みのる 編集日時 2004-08-15 15:55 ]

質問者:みのる

回答

ConnectionTimeoutの設定を変えてみるのはどうでしょうか。

投稿者:CARA

編集 履歴 (0)

CARAさん、ありがとうございます。

ConnectionTimeoutの設定を変えてみるのはどうでしょうか。

早速、以下の通りにしてみました。
m_cn.ConnectionString = m_strDbConstr & _
"UID=" & m_strDbUser & ";" & _
"PWD=" & m_strDbPassword & ";" & _
"Connect Timeout = 300"

m_cm.CommandTimeout = 300

残念がら、同じエラーが出てしまいました。。。

投稿者:みのる

編集 履歴 (0)

扱うデータの件数を増やしテストをしています。
1万件、5万件、10万件、50万件
10万件までのテストはできるのに、
50万件のテストで上記のエラーが発生します。
直接SQL文を実行した場合は、エラーが発生しません。
直接SQL文を実行した場合というのはSQLクエリアナライザとかのツールですか?
各データ件数での直接SQL文を実行した場合の所要時間はどれ位でしょうか?
_________________えムナウ Microsoft MVP for Visual Developer - C#,2005/01-2007/12
えムナウのプログラミングのページ Blog1 Blog2

投稿者:えムナウ

編集 履歴 (0)

10万件までのテストはできるのに、

50万件のテストで上記のエラーが発生します。

多量の delete に時間がかかるのは、ある程度仕方ありません。

タイムアウトを延ばして50万件のテストを通過したとしても、100万件のテストは通過しないかもしれないし、高負荷時には50万件の処理でもタイムアウトするかもしれません。

こういう場合、設計自体を見直すのが最も効果的です。

私が良く使う手は

・各レコードに「削除フラグ」の列を追加する。
・通常の「削除」処理は「削除フラグ」を true にするだけ。
・夜間バッチなどで「削除フラグ」が true なものを一括 delete する。

です。

バッチが使えない場合は、新規レコードの挿入時に削除マークのついたレコードを1個以上 delete するなどの工夫が必要です。

_________________// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/

投稿者:渋木宏明(ひどり)

編集 履歴 (0)

ひょっとしたらこの処理自体がバッチ処理ではないですか?
バッチ処理でしたらストアドプロシージャで運用することを検討してみてください。
_________________えムナウ Microsoft MVP for Visual Developer - C#,2005/01-2007/12
えムナウのプログラミングのページ Blog1 Blog2

投稿者:えムナウ

編集 履歴 (0)

たくさんの方々、いろいろとご指導ありがとうございます。

そして、遅れてしまってすみません。

えムナウさんのアドバイスで、タイムアウトの時間を増やしてみました。
50万件成功です。
100万件は失敗です。

渋木宏明(ひどり)さんの言うとおりです。。

残念ながら
設計上、渋木宏明(ひどり)さんの方法はちょっと難しいと思われます。

えムナウさんの「ストアドプロシージャで運用」というのは
タイムアウトを気にしなくて言いのでしょうか?

ちらっと調べたのですが、
「DataReaderにストアドプロシージャを渡すせばいい」と
どこかのHPに書いてありました。

っていうことは、タイムアウト気にしないといけないのでは??

お手数ですが、.NETではどのようにストアドプロシージャで運用するのか
教えていただけませんか?
(VB6.0と同じでいいのでしょうか?)

投稿者:みのる

編集 履歴 (0)

 いったんインデックスや外部参照を無効にすれば、早くはなります。どれくらい効率があがるかは、張ってあるインデックスなどによります。

投稿者:Jitta

編集 履歴 (0)

えムナウさんの「ストアドプロシージャで運用」というのは

タイムアウトを気にしなくて言いのでしょうか?

そういう訳にはいきません。
一般に、DB内部で完結する処理であれば、無駄なデータ転送が発生しない分、ストアドプロシジャの方が効率的に処理できるというだけのことです。
ストアドプロシジャでの処理が複雑で時間がかかれば、やはりタイムアウトしてしまいます。

設計を大きく変更できないとしても、100万件を削除する時には10万件ごと10回の削除に分割するなど、なにかしら工夫しないと、どうしようもないと思います。
_________________// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/

投稿者:渋木宏明(ひどり)

編集 履歴 (0)

いろいろと、ご相談に乗っていただいてありがとうごいます。

・インデックス
・ストアド
・設計

もう一度見直しします。

あと、.NETからストアドを実行するための参考になるHP等があれば
大変ありがたいのですが。。。

投稿者:みのる

編集 履歴 (0)

あと、.NETからストアドを実行するための参考になるHP等があれば

通常のクエリ実行と同じです。

SqlCommand を組み立てて、結果セットを返すかどうかなどの違いで ExecuteReader() あるいは ExecuteNonQuery() します。

_________________// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/

投稿者:渋木宏明(ひどり)

編集 履歴 (0)

渋木宏明(ひどり)さん、ストアドの実行できました!!

ふー。

あとは、もっとも重要な設計の見直しです。頑張ります。

設計の見直しで「SQLServerのトランザクションログの管理」
にも悩んでおります。

バッチは大量のデータを扱うので、その分ログも大きくなります。

オラクルとは違って、SQLServerは管理しないといけないと思うのですが
.NET側では、皆さんどうされていますか?

ログのバックアップとか、ログの削除とか。。。。

投稿者:みのる

編集 履歴 (0)
ウォッチ

この質問への回答やコメントをメールでお知らせします。