- - PR -
FETCHが遅い
投稿者 | 投稿内容 |
---|---|
|
投稿日時: 2005-12-12 20:17
ORACLEで以下のようにカーソルとループを使って複数のテーブルからデータを取得しています。
OPEN CUR1 FOR SQL1; LOOP FETCH CUR1 INTO REC1; IF CUR1%NOTFOUND THEN EXIT; END IF; -- 処理 -- END LOOP; フェッチの部分を計測したところ、最終行のフェッチが終わってから次の行をフェッチするのに 数十秒かかっていました。 ちなみに1行目から最終行までのフェッチは、1秒もかかりません。 試しに、1テーブルから取得するようにしたところ、フェッチ時間の差はありませんでした。 ということは、複数のテーブルからデータを取得するような複雑なSQLを発行するときに、 フェッチ時間の差ができる(処理時間が長くなる)ということなのでしょうか? 時間の差が出ないようにする(処理時間を短くする)方法があるのでしょうか? 何かご存知の方がいらっしゃいましたら教えてください。 [ メッセージ編集済み 編集者: とわき 編集日時 2005-12-13 09:28 ] |
|
投稿日時: 2005-12-13 12:24
SQLを見直すか、INDEXを作成するなどのパフォーマンスチューニングの必要があるかと思います。
|
|
投稿日時: 2005-12-13 13:18
ご返答ありがとうございます。
確かに少し複雑なSQL文ですが、INDEXを作成してうまく使われるように作っているので、SQLPLUSで発行すると1秒かからないくらいで結果は返ってきます。 最終行の次の行のFETCHに時間がかかっているのは、どうしようもないものなのでしょうか…。 |
|
投稿日時: 2005-12-13 14:48
> 最終行のフェッチが終わってから次の行をフェッチするするのに
> 数十秒かかっていました。 これは「最後にフェッチの処理をしてから、IF CUR1%NOTFOUND THEN でループを抜けるまでの間に数十秒かかる」って意味ですよね。 何か全件検索している臭いけど、でもSQLPlusで遅くないというのはどうしたことか。 フェッチ後の、-- 処理 -- の部分を省略しても一緒でしょうか? それから(これはあまり意味は無いかもしれませんが)ループ文を DECLARE CURSOR CUR1 IS SELECT ・・・・ BEGIN FOR REC1 IN CUR1 LOOP -- 処理 -- END LOOP; END; と変更したら変化はあるでしょうか? |
|
投稿日時: 2005-12-13 15:26
Desmoさん、ご返答ありがとうございます。
そうなんです。 例えば、100件取れるSELECT文だとすると、100件目(最終行)のFETCH→処理が終わって、101件目(存在しない行)のFETCHが遅いのです。 ↓このロジックで計測しました(処理ロジックは入れていません) OPEN CUR1 FOR SQL1; LOOP DBMS_OUTPUT.PUT_LINE('FETCH前 ' || TO_CHAR(SYSDATE,'HH24:MI:SS')); FETCH CUR1 INTO REC1; DBMS_OUTPUT.PUT_LINE('FETCH前 ' || TO_CHAR(SYSDATE,'HH24:MI:SS')); IF CUR1%NOTFOUND THEN EXIT; END IF; END LOOP; カーソルFORループでも試してみましたが、同じでした。 最後の'ループ内〜〜〜'のログで出てから数十秒後に'ループ外〜〜〜'のログが出ていました。 ↓このロジックで計測しました(処理ロジックは入れていません) DECLARE CURSOR CUR1 IS SELECT 〜〜〜; BEGIN FOR REC1 IN CUR1 LOOP DBMS_OUTPUT.PUT_LINE('ループ内 ' || TO_CHAR(SYSDATE,'HH24:MI:SS')); END LOOP; DBMS_OUTPUT.PUT_LINE('ループ外 ' || TO_CHAR(SYSDATE,'HH24:MI:SS')); END; |
|
投稿日時: 2005-12-13 16:35
こんにちわ。
HWMが高すぎて、EOFが返るまでのブロック読み込みに時間が掛かっているので あれば・・・・ 一旦別のテーブルにCOPYしておいて、元のテーブルをTRUNCATE TABLEし 再度データを戻してから実行したらどうなりますか? 但し、SQL*PLUSとの実行時間の違いについての検証にはなりません。 SQL*PLUSで実行した際の実行計画と、PL/SQLから実行した際の実行計画は 同一のものですか? |
|
投稿日時: 2005-12-13 17:05
原因を追究するのがめんどかったらBULK COLLECT INTOを利用して書き直してしまうという手もあります。
|
|
投稿日時: 2005-12-13 20:08
ZingBayさん、Anthyhimeさん、ご返答ありがとうございます。
ZingBayさんへ HWM、少し勉強させて頂きました。 今回3つのテーブルを結合してデータを取得しようとしているのですが、この場合もHWMが関係してくるのでしょうか? もし関係するのであれば、発行したSQLにおいてのHWMを確認できる方法はありますか? Anthyhimeさんへ 1件ずつFETCHするよりも一気にコレクションとして取得した方が速いですか? |