[pgsql-jp: 25046] Re: optimizerの動作
Masaru Sugawara
rk73 @ sea.plala.or.jp
2002年 3月 2日 (土) 00:15:10 JST
すがわら/RK73です。
Message-ID:<03f201c1c0fa$facadb80$0300a8c0 @ lucy2k>
Mail-Count: Date&Time:2002/03/01 17:27:46
ARAI Shunichi <arai @ mellowtone.org>さんのφ(..@)について
> table foo (id1 integer, id2 integer)
> table bar (id2 integer, updated timestamp)
>
> というようなテーブルがあります。(全て索引付き)
>
> SELECT updated FROM foo,bar WHERE id1=? AND foo.id2=bar.id2
> ORDER BY updated DESC LIMIT 100;
>
> そこで、上のようなクエリを発行します。
>
> すると、foo.id1 = ?に一致するレコードが1件しかない場合と2件以上の
> 場合で、クエリプランが大きく変わります。
>
> 1件しかない場合、
> Limit (cost=2779.06..2779.06 rows=100 width=377)
> -> Sort (cost=2779.06..2779.06 rows=1130 width=377)
> -> Nested Loop (cost=0.00..2721.75 rows=1130 width=377)
> -> Seq Scan on foo ...
> -> Index Scan using bar_id2_idx on bar ...
> 2件以上の場合、
> Limit (cost=0.00..1278.44 rows=100 width=377)
> -> Nested Loop (cost=0.00..63872.07 rows=4996 width=377)
> -> Index Scan Backward using bar_updated_idx on bar ...
> -> Seq Scan on foo (cost=0.00..1.60 rows=6 width=4)
> となります。
上記のプランを見ると...以下が削除されてしまっているので
はっきりわかりませんが、効率的なインデックスを使っていない
ようです。id2に作ったインデックスを削除してしてから実行し
てみていただけないでしょうか。それでもだめなら、updateに
張ったインデックスも削除してみていただけないでしょうか。
id1のインデックスのみ残します。
また、ver7.2なので、explain analyzeの方がよりわかりやすく
なるかと思います。
以下のようなプランが生成されると、CPUのパワーにもよりますが
一般的に高速になるのですが...
-> Hash Join
-> Seq Scan on bar
-> Hash
-> Index Scan using foo_id1_idx on foo
>
> とうぜん全件をソートしない後者のほうがずっと高速です。
> 実際にかなりの速度差が出てしまい、仕方なくenable_sortをオフにして
> 使っています。(すると、全て後者のようになり、高速に動作します。)
>
> これは私のテーブル設計やクエリの立て方に問題があるのでしょうか?
> それともオプティマイザの仕様であって、enable_sortをオフにして使えば
> 良いのでしょうか。
>
> バージョンはpostgres 7.2です。
--------------------------------
Masaru Sugawara
e-mail:rk73 @ sea.plala.or.jp
-------------------------------
pgsql-jp メーリングリストの案内