最小限の例として次の再帰CTEを使用していますが、一般的に、オプティマイザは再帰CTEにデフォルトの「推測」カーディナリティを使用する必要があります。
with recursive w(n) as ( select 1 union all select n+1 from w where n<5 ) select * from w;
/*
n
---
1
2
3
4
5
*/
explain analyze
with recursive w(n) as ( select 1 union all select n+1 from w where n<5 ) select * from w;
/*
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
CTE Scan on w (cost=2.95..3.57 rows=31 width=4) (actual time=0.005..0.020 rows=5 loops=1)
CTE w
-> Recursive Union (cost=0.00..2.95 rows=31 width=4) (actual time=0.003..0.017 rows=5 loops=1)
-> Result (cost=0.00..0.01 rows=1 width=0) (actual time=0.001..0.001 rows=1 loops=1)
-> WorkTable Scan on w w_1 (cost=0.00..0.23 rows=3 width=4) (actual time=0.002..0.002 rows=1 loops=5)
Filter: (n < 5)
Rows Removed by Filter: 0
*/
上記の計画のrows=31
推定rows=5
カーディナリティと実際のカーディナリティに注意してください。100が推定値として使用されているように見える場合もありますが、推測の背後にある正確なロジックはわかりません。
私の現実の問題では、カーディナリティの見積もりが悪いため、高速な「ネストされたループ」プランを選択できません。再帰CTEがオプティマイザのカーディナリティを「ヒント」にしてこれを回避するにはどうすればよいですか?
COST
機能はありますが、それ以外はあまりありません。私はpgsql-hackersでそれを上げることをお勧めしますが、「ヒント」の議論のn番目の反復に巻き込まれ、大量の熱気を浪費し、何も達成しません:-(