Estoy usando el siguiente CTE recursivo como un ejemplo mínimo, pero en general, el optimizador tiene que usar cardinalidades 'adivinadas' predeterminadas para los CTE recursivos:
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
*/
Tenga en cuenta las cardinalidades rows=31
estimadas y rows=5
reales en el plan anterior. En algunos casos, 100 parece usarse como una estimación, no estoy seguro de la lógica exacta detrás de las conjeturas.
En mi problema del mundo real, la pobre estimación de la cardinalidad impide que se elija un plan rápido de 'bucles anidados'. ¿Cómo puedo 'insinuar' la cardinalidad del optimizador para que un CTE recursivo evite esto?
COST
funciones, pero no mucho más. Sugeriría plantearlo en pgsql-hackers, pero te quedarías atrapado en la enésima iteración del debate de "pistas", desperdiciando masas de aire caliente y sin lograr nada :-(