Używam następujących rekurencyjnych CTE jako minimalnego przykładu, ale ogólnie optymalizator musi używać domyślnych „zgadywanych” liczności dla rekurencyjnych 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
*/
Zanotuj rows=31
szacunkowe i rows=5
rzeczywiste liczności w powyższym planie. W niektórych przypadkach wartość 100 wydaje się być używana jako wartość szacunkowa, nie jestem pewien, czy dokładna logika kryje się za domysłami.
W moim prawdziwym problemie słabe oszacowanie liczności uniemożliwia wybór planu „zagnieżdżonych pętli”. Jak mogę „zasugerować” liczność optymalizatora dla rekurencyjnego CTE, aby obejść ten problem?
COST
funkcje, ale niewiele więcej. Sugerowałbym podniesienie go na hakerów pgsql, ale wpadlibyście w n-tą iterację debaty „podpowiedzi”, marnując mnóstwo gorącego powietrza i nie osiągając niczego :-(