Я использую следующий рекурсивный 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-хакерах, но вы бы просто оказались втянутыми в n-ю итерацию дебатов о «подсказках», тратя массу горячего воздуха и ничего не добиваясь :-(