今日は、理解できないクエリ プランについて頭を悩ませるのに 1 時間以上費やしました。クエリは で、UPDATE
まったく実行されませんでした。完全にデッドロック:pg_locks
何も待っていないことを示しています。さて、私は自分自身が最高のクエリ プラン リーダーだとも最低のクエリ プラン リーダーだとも思っていませんが、これは非常に難しいと思います。私はこれらをどのように読むのだろうかと思っています。エラーを特定するために Pg エースが従う方法論はありますか?
この問題を回避する方法については別の質問をする予定ですが、今はこれらのタイプの計画の読み方について具体的に話しています。
QUERY PLAN
--------------------------------------------------------------------------------------------
Nested Loop Anti Join (cost=47680.88..169413.12 rows=1 width=77)
Join Filter: ((co.fkey_style = v.chrome_styleid) AND (co.name = o.name))
-> Nested Loop (cost=5301.58..31738.10 rows=1 width=81)
-> Hash Join (cost=5301.58..29722.32 rows=229 width=40)
Hash Cond: ((io.lot_id = iv.lot_id) AND ((io.vin)::text = (iv.vin)::text))
-> Seq Scan on options io (cost=0.00..20223.32 rows=23004 width=36)
Filter: (name IS NULL)
-> Hash (cost=4547.33..4547.33 rows=36150 width=24)
-> Seq Scan on vehicles iv (cost=0.00..4547.33 rows=36150 width=24)
Filter: (date_sold IS NULL)
-> Index Scan using options_pkey on options co (cost=0.00..8.79 rows=1 width=49)
Index Cond: ((co.fkey_style = iv.chrome_styleid) AND (co.code = io.code))
-> Hash Join (cost=42379.30..137424.09 rows=16729 width=26)
Hash Cond: ((v.lot_id = o.lot_id) AND ((v.vin)::text = (o.vin)::text))
-> Seq Scan on vehicles v (cost=0.00..4547.33 rows=65233 width=24)
-> Hash (cost=20223.32..20223.32 rows=931332 width=44)
-> Seq Scan on options o (cost=0.00..20223.32 rows=931332 width=44)
(17 rows)
このクエリプランの問題-私は理解していると思います-おそらく次のことを最もよく言いますRhodiumToad
(彼は間違いなくこれに優れているので、彼の説明が優れていることに賭けます)irc://irc.freenode.net/#postgresql
:
ああ、その計画は悲惨な可能性があります。その計画の問題は、各行に対して非常に高価なハッシュジョインを実行していることです 。問題は、他の結合からのrows = 1の推定であり、プランナーは、内部外側のパスが 1 つの行のみを返すと推定されるネストループのパス。明らかに、プランナーの見積もりでは、高価な部分は一度だけ実行されますが、これは実際には本当に台無しになる明らかな傾向があるため、問題は、プランナーが自分の見積もりを理想的に信じていることです。 1行を返す」および「1行以上を返すことはできません」が、それを既存のコードに組み込む方法がまったく明確ではありません
彼は続けてこう言います:
どの結合にも影響する可能性がありますが、通常はサブクエリに対する結合が最も可能性が高いです
この計画を読んだとき、最初に気づいたのは でNested Loop Anti Join
、これには のコストがかかりました169,413
(上限に固執します)。Nested Loop
この Anti-Join は、 at cost of31,738
の結果とHash Join
at a cost ofの結果に分解され137,424
ます。現在、137,424
はよりもはるかに大きい31,738
ので、問題はハッシュ結合であることがわかりました。
EXPLAIN ANALYZE
次に、クエリの外にある Hash Join セグメントに進みます。7秒で実行されました。(lot_id、vin)、および (co.code、および v.code) にインデックスがあることを確認しました -- ありました。個別に無効seq_scan
にhashjoin
すると、2 秒未満の速度の増加に気付きました。1 時間後に進行しなかった理由を説明するのに十分ではありません。
しかし、結局、私は完全に間違っています!はい、それはクエリの遅い部分でしたが、rows="1"
ビットのためです(私はそれがにあったと思いますNested Loop Anti Join
)。これは、行の量を誤って見積もるプランナーのバグ (能力の欠如) ですか? 同じ結論に達するために、これをどのように読むべきRhodiumToad
ですか?
それは単にrows="1"
私がこれを理解するきっかけになるはずですか?
関連するすべてのテーブルで実行VACUUM FULL ANALYZE
しましたが、これは Postgresql 8.4 です。