0

約10億行のテーブルがあります。私は唯一のユーザーなので、ロックなどの競合はありません。次のようなものを実行すると、次のことに気付きました。

DECLARE   
  CURSOR cur IS SELECT col FROM table where rownum < N; 
BEGIN
  OPEN cur;
  LOOP
    dbms_output.put_line("blah")
  END LOOP;
  CLOSE cur;
END;

Enterキーを押してから、出力が流入し始めるまでに遅延があります。Nが小さい場合、それは重要ではありません。Nが大きい(またはWHERE句がない)場合、この遅延は時間のオーダーになります。

お分かりのように、私はOracleを初めて使用します。カーソルは、ループの反復ごとに更新されるポインタをテーブルに保持するだけだと思いました。したがって、反復が実行されるテーブルのサイズに比例するラグは予想していませんでした。これは間違っていますか?カーソルは、クエリ結果を反復処理する前に、クエリ結果全体をロードしますか?

最初のオーバーヘッドなしでテーブルを行ごとに繰り返す方法はありますか?

4

2 に答える 2

9

表示されているのは、プログラムが終了するまで、DBMS_OUTPUT.PUT_LINEからの出力が表示されないことです。クエリが最初の行を返す速度については何もわかりません。(例では、実際にデータをフェッチするつもりだったと思います)。

セッションを監視する方法はたくさんあります。1つは次のようなものです。

DECLARE   
  CURSOR cur IS SELECT col FROM table; 
  l_col table.col%ROWTYPE;
BEGIN
  OPEN cur;
  LOOP
    FETCH cur INTO l_col;
    EXIT WHEN cur%NOTFOUND;
    dbms_application_info.set_module('TEST',l_col);
  END LOOP;
  CLOSE cur;
END;

それが実行されている間に、別のセッションから実行します。

select action from v$session where module='TEST';

カーソルが行をフェッチするにつれて、ACTIONの値が変化し続けることがわかります。

于 2010-03-10T17:18:49.930 に答える
0

また、Oracleオプティマイザによって「長い操作」と見なされる操作についてv$session_longopsを監視するのが好きです。

メッセージを選択します。time_remainingfromv$session_longops where time_remaining> 0;

于 2010-03-17T22:03:53.013 に答える