[pgsql-jp: 32028] Re: count が以上に遅い。

T.Suzuki t_suzuki @ kenwood-eng.co.jp
2004年 1月 15日 (木) 12:36:41 JST


鈴木@KEGと申します.

# 件名から大分それて,「Where句の評価順」の話題となっています.

> > > 質問なんですが、上記の条件式に関する評価というのは
> > > オプティマイザがよきにはからってくれたりはしないのでしょうか?

「条件式に関する評価」を「よきにはからって」というのは,
「コストが低い条件式を優先して実行してくれるのでは?」
という意味に取りました.
結論としては無いはずです.

> > Where句に,「A and B」といった式があったとして,
> > AとBのどちらを先に評価しても,結果は同じですが
> > オプティマイザがこの順序を変えるという話しは,聞いた事はありません.
> 
> 商用DBの場合はcardinality大小ないしは、インデックスのありなしで
> プランはかわったりします。

WHERE句の条件式は,パーサが解析し「構文解析ツリー」に変換されます.
プランナ/オプティマイザは,構文解析ツリー内で"リレーション"部分の
実行方法(indexを使う等)を最適化します.
リレーション毎にコストを見積もりプランを決定しますが,
その結果で,どのリレーションがコストが低くて優先して実行するかという事は
行っていません.
Where句の条件実行順をプランナ/オプティマイザは把握していない
(する必要がない?)はずです.


> > # 勝手に変わったら,不具合になってしまうので...
> > 単純に式の評価順(C言語とかと同じ)です.
> 
> 不具合なんですか?
これに関して,実験用のSQLファイルを切り出した物を末尾に記載しました.

例えばWhere句中で,ログを記録するような関数等(例ではSEQUENCE)を実行した場合,
Where句の条件がどこまで実行されるかで,結果が異なってしまいます.
もし,「A and B」の順序をパーサ,プランナ,オプティマイザが「最適化」と称して
変えることがあったら,意図した結果にならない事を伝えたかったのです.

# 例に挙げるSQLは,バグを生む元なので推奨してるわけではありませんが,
# 実験として強引に作りました.

> > > cardinalityとかを意識して、プログラマが評価順を
> > > 指定しないといけない??
> > >
> > A and B とするか,B and A に書き換えるかといった事は,
> > 今回のように Likeや複問い合わせを含むSQLの場合に
> > 実行時間が大きく変わる場合があったので注意しています.
> 
> 静的なオプティマイザの場合は大きくかわる場合があるかと
> 思いますが、動的なオプティマイザの場合は、評価の順番も
> ふくめて最適化を試みるのかなぁと思っています。

静的/動的の違いは詳しくない為,自信はないですが
先に述べた通り,Where句の評価の順番とオプティマイザの仕事は関連が無いので,
プログラマが書いた通りに実行されると思います.

# だんだん,自信が無くなって来たので
# 間違っていたら,突っ込みして下さいますようお願いします.
 -----------------------------------------
      鈴木 徹 (SUZUKI Toru)
      KENWOOD ENGINEERING CORPORATION
      E-mail:t_suzuki @ kenwood-eng.co.jp
 -----------------------------------------

-----------------------------------------------
/**
 * [pgsql-jp: 32026] 解答用の実験
 * @date    2004-01-15 10:13
 * @todo    psql  dbname  -f  this_save.sql
 */
DROP TABLE hoge;
CREATE TABLE hoge
(
  no serial NOT NULL,
  count int4,
  CONSTRAINT hoge_pkey PRIMARY KEY ("no")
);

DROP SEQUENCE run_count_seq;
CREATE SEQUENCE run_count_seq;

--no = 1, count_1 = 1, count_2 = 1
INSERT INTO hoge(count) VALUES( NEXTVAL('run_count_seq') );

--last_val = 1 ?
SELECT last_value AS "last_value TEST" FROM run_count_seq;

/* TRUE and FALSE */
SELECT SETVAL('run_count_seq', 1) AS "run_count_seq reset";

SELECT no FROM hoge
WHERE NEXTVAL('run_count_seq') > 0 AND NEXTVAL('run_count_seq') < 0;

-- NEXTVALは何回実行されたか? ( 2 回で,3が表示されるはず)
SELECT last_value AS "TRUE and FALSE" FROM run_count_seq;

/* FALSE and FALSE */
SELECT SETVAL('run_count_seq', 1) AS "run_count_seq reset";

SELECT no FROM hoge
WHERE NEXTVAL('run_count_seq') < 0 AND NEXTVAL('run_count_seq') < 0;

-- NEXTVALは何回実行されたか? ( 1 回で,2が表示されるはず)
SELECT last_value AS "FALSE and FALSE" FROM run_count_seq;

--All Clean
/*
DROP TABLE hoge;
DROP SEQUENCE run_count_seq;
DROP SEQUENCE run_count_seq;
*/



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