[pgsql-jp: 30403] Re: カーソルに対するSELECT

Hiroki Kataoka kataoka @ interwiz.jp
2003年 7月 5日 (土) 23:07:53 JST


片岡です。

At 05 Jul 2003 19:35:38 +0900 Makoto,Yui wrote:
> >   PostgreSQLのカーソルでは、たとえば1行フェッチする場合だとクエリから1行が
> > 得られた時点で処理を中断して返ってきますので、コスト的に意味のあるパターン
> > も考えられます。
> 
> PostgresのカーソルもバックエンドはResult set一度作っていると, 
> 僕も理解していたのですが違ったでしょうか.

  Result setは作っていないです。それをするとResult setだけでサーバのメモリ
を使い尽くすような膨大な行のSELECTが絶対に出来なくなってしまいます。それに
FETCH 1などで1行だけ欲しいと言ったときに、1行の結果が取り出せた時点で処理
を中断できれば無駄が少なくて済みます(クライアントが最終行までFETCHしてく
れる保証はないわけですし…)。

> カーソルって基本的にクライアントに結果を分けておくることで(クライアントの)
> メモリの消費を抑えるものですよね.

  その通りだと思いますが、だからといってサーバ側でResult setを丸ごと持つ必
要もないと思います。

> PL/PGSQLのカーソルに限って言えば, その通りではないようですが.
> http://www.postgresql.jp/document/pg732doc/programmer/plpgsql-cursors.html
> 
> 例えば, FOR myrec IN SELECT * FROM node LOOP
> なんかでは, FOR ループは自動的に*カーソル*を内部的に使用してメモリの問題を防ぐ.
> とあります.
> 
> 実際FOR LOOPではselect分が複数回走っていました.
> #PLANが再利用されるとは言え, この選択は微妙な気もしますが...
> #シーケンシャルスキャンか結果セットのサイズによっては逆効果ですよね.

  PL/PGSQLのFORが実際にどうなっているかを調べたことがないのでこの辺は想像
になってしまいますが、ドキュメントで言っているところの「FORではカーソルを
利用している」とは、プランを再利用するためではなく、単にFORのループ処理の
ためにカーソルを使っているということだと思います。カーソルでは結果セットを
あらかじめ作成したりしませんから、エグゼキュータから1行目の結果が得られれ
ばすぐにでもループ処理を開始できることになります。

> 実際, 以前作ったものでFOR LOOPのSELECTがボトルネックになっていました.

  こちらはわかりませんが、

> 実装がどうなっているか(OFFSET使ってるかとか)は調べてないので的外れだったらすいません.

  OFFSETを使っているということはないと思います(カーソルを使っているわけで
すから)。

-- 
Hiroki Kataoka <kataoka @ interwiz.jp>



pgsql-jp メーリングリストの案内