[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 メーリングリストの案内