web-dev-qa-db-ja.com

このクエリプランを選択するpostgresの理由を理解する

クエリを実行しました:

select * from orderline where orderid = 12345 and status > 0

それは私に次の計画を与えました:

Bitmap Heap Scan on orderline  (cost=286370.00..531410.78 rows=76372 width=155)
  Recheck Cond: ((orderid = 12081976) AND (itemstatus > 0))
  ->  BitmapAnd  (cost=286370.00..286370.00 rows=76372 width=0)
        ->  Bitmap Index Scan on orderline_orderid_index  (cost=0.00..4239.65 rows=229117 width=0)
              Index Cond: (orderid = 12081976)
        ->  Bitmap Index Scan on orderline_status  (cost=0.00..282091.91 rows=15274484 width=0)
              Index Cond: (status > 0)

Postgresがforignキーのフィルターではなく2つの別々のインデックススキャンを実行することにした理由を理解したかった(orderline_orderid-これは数百万行のうち約5行を返します)次に、これらの結果からstatusをフィルタリングします。

ここで間違って設定したものをどのように解決できますか? (私はインデックスの断片化を想定していますか、それともステータスにインデックスを含めるべきではありませんか?)

編集:コメントにあるいくつかのことを試したところ、次のことがわかりました。

問題の原因はインデックスを削除したことであると考え、問題は解決しました。

Bitmap Heap Scan on orderline  (cost=4258.75..597209.93 rows=76372 width=155)
  Recheck Cond: (orderid = 12081976)
  Filter: (status > 0)
  ->  Bitmap Index Scan on orderline_orderid_index  (cost=0.00..4239.65 rows=229117 width=0)
        Index Cond: (orderid = 12081976)

ただし、インデックスを削除して追加し、分析を実行すると、次のことが発生しました。

Index Scan using orderline_orderid_index on orderline  (cost=0.00..14.87 rows=4 width=63)
  Index Cond: (orderid = 12085242)
  Filter: (status > 0)

これは、インデックスを再構築したためですか、それとも分析を実行したためですか?

2
Mr Shoubs

Postgresはあなたの値がどのように分配されているのか見当がつかなかったようです。実際には5行だったのに、orderid = 12081976の行が229117行あると推測されました。次に、229117行に最適なプランを選択しました。

analyzeを実行すると、テーブル内の値の分布に関する統計を生成して保存することができました。そして、このorderidには約4行あることがわかりました。そして、これにより、より良い計画を選択することができました。

したがって、これを引き起こしたのはanalyzeです。データベースデータに大きな変更を加えた後(たとえば、外部ソースからインポートした後)に実行することを忘れないでください。

また、計画を分析するときは、explain analyze [query];だけでなくexplain [query];を使用してみてください。形式を理解しやすくするために、 explain.depesz.com に貼り付けることができます。

1
Tometzky