- PR -

T-SQLでのループ処理について

1
投稿者投稿内容
せんこ
会議室デビュー日: 2004/04/26
投稿数: 18
投稿日時: 2005-04-07 13:18
こんにちは。

T-SQLでのループ処理についてわかる方がいましたら教えてください。

[メニューマスタ]と[メニュー申込テーブル]があるのですが、[メニューマスタ]に
登録されているメニュー毎に[メニュー申込テーブル]にある件数を取得しようと
しています。
そこで以下のような処理を行おうとしたのですが、パフォーマンスがとても悪く
苦労しています。

CURSORやWHILEを使用して、[メニューマスタ]から順にメニューコードを取得し、
[メニュー申込テーブル]での検索条件に取得したメニューコードを指定して件数を
取得しようとしています。
条件には他にも年や月なども指定しているのですがそれは引数で指定しています。

一つ一つの処理を行うのは数秒で行えるのにループ処理を行うと時間がかかるので、
処理を抜粋して実行させてみると条件で@変数を使用すると時間がかかり、
直接メニューコードや年月を指定すると早いことがわかりました。

T-SQLの中で処理しようとするとどうしても@変数を使用しなければならないので
解決には至っていません。

ここで質問なのですが、ループの中(連続した処理)で@変数を多用するとパフォーマンス
が悪くなるものなのでしょうか?

環境はSQL Server7.0ですが、SQL Server 2000でも同様でした。
(OSはWindows2000。)

以上、よろしくお願いします。

# 実際のコードって必要でしょうか?
結構長くなるので省略しました。
あき
ベテラン
会議室デビュー日: 2003/07/23
投稿数: 72
投稿日時: 2005-05-05 00:47
クエリの条件の部分に変数を使用すると処理が遅くなる事があります。
この場合、検索条件にユニークインデックスが含まれないことが考えられます。
クエリオプティマイザが変数だとテーブルスキャンを選択するようです。
回避策としては、ヒント文を入れるといいでしょう。
せんこ
会議室デビュー日: 2004/04/26
投稿数: 18
投稿日時: 2005-05-11 11:06
引用:

あきさんの書き込み (2005-05-05 00:47) より:
クエリの条件の部分に変数を使用すると処理が遅くなる事があります。
この場合、検索条件にユニークインデックスが含まれないことが考えられます。
クエリオプティマイザが変数だとテーブルスキャンを選択するようです。
回避策としては、ヒント文を入れるといいでしょう。




あき様、しばらく見ていなかったので気付きませんでしたがご返答ありがとう
ございました。

ヒント文というものを知らなかったのですが、例えば
 SELECT au_lname FROM authors WITH (NOLOCK)
という内容でよかったでしょうか?

勉強不足のためあき様のご返答がいまいちわからないのですが、
変数を使用するとユニークインデックスでないインデックスを利用できないので
テーブルヒントにINDEX=とインデックスを指定するとパフォーマンスが改善する
という内容でよかったでしょうか?

質問の内容を簡潔にしようとしていたため、先回の質問内容ではテーブルから直接
件数を取得する旨書いたのですが、実際はビューから件数を取得していました。
テーブルとビューとでは内容が異なるということはありますでしょうか?

先回の質問でのメニューマスタは約50件あり、ビューでは数万件のテーブルを複数
連結させています。連結条件においては必ずインデックス(クラスタ化インデックス・
非クラスタ化インデックス)を使用しています。
こちらで確認した際に変数を用いた場合と用いない場合とでパフォーマンスが異なって
いたのであまり気にしませんでした。
水谷
会議室デビュー日: 2004/05/07
投稿数: 17
お住まい・勤務地: 福島県
投稿日時: 2005-05-11 11:43
詳しいことが分からないので的外れかもしれませんが。

単純に[メニュー申込テーブル](ビューでもいいですが)を
メニューコードでグループ化して COUNT を取ってはだめでしょうか?
([メニューマスタ]にある項目が検索条件や結果に必要であれば
メニューコードで結合すれば良いでしょう)
せんこ
会議室デビュー日: 2004/04/26
投稿数: 18
投稿日時: 2005-05-11 12:04
引用:

水谷さんの書き込み (2005-05-11 11:43) より:
詳しいことが分からないので的外れかもしれませんが。

単純に[メニュー申込テーブル](ビューでもいいですが)を
メニューコードでグループ化して COUNT を取ってはだめでしょうか?
([メニューマスタ]にある項目が検索条件や結果に必要であれば
メニューコードで結合すれば良いでしょう)




こんにちは。

最初はGROUP BYによるグループ化により件数を取得しようとしたのですが、
0件の場合は、0とは表示されず戻り値がなかったので先回のメールのように
しました。
0件と表示されるようなクエリが作成できればその方が望ましいです。
ごー
ベテラン
会議室デビュー日: 2003/08/29
投稿数: 51
お住まい・勤務地: いるかホテル
投稿日時: 2005-05-11 12:24
こんにちは。

引用:


最初はGROUP BYによるグループ化により件数を取得しようとしたのですが、
0件の場合は、0とは表示されず戻り値がなかったので先回のメールのように
しました。
0件と表示されるようなクエリが作成できればその方が望ましいです。




なら、サブクエリではどうでしょうか?
カーソルより速い気がします。

こんなかんじ↓

Select
メニューマスタ.メニューコード ,
(select count(*) From メニュー申込テーブル Where メニュー申込テーブル.メニューコード= メニューマスタ.メニューコード )
From メニューマスタ


_________________
1

スキルアップ/キャリアアップ(JOB@IT)