재귀 CTE의 카디널리티를 어떻게 '힌트'합니까?


10

다음 재귀 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가이 문제를 해결하려면 옵티 마이저 카디널리티를 어떻게 '힌트'할 수 있습니까?


5
이것은 통계 힌트가 정말 좋은 많은 경우 중 하나입니다. 있다 COST하지만 많은 다른 함수에. pgsql-hackers에서 올리는 것이 좋습니다만, 당신은 "힌트"토론의 n 번째 반복에 갇히고, 많은 양의 열기를 낭비하고 아무것도 달성하지 못할 것입니다 :-(
Craig Ringer

답변:


8

나는이 문제를 해결하기 위해 노력했지만 덜 덜한 방법이 있기를 바라고 있습니다.

explain analyze
with recursive w(n) as ( select 1 union all select n+1 from w where n<5 )
select * from w limit (select count(*) from w);
/*
                                                    QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
 Limit  (cost=3.66..3.72 rows=3 width=4) (actual time=0.032..0.034 rows=5 loops=1)
   CTE w
     ->  Recursive Union  (cost=0.00..2.95 rows=31 width=4) (actual time=0.003..0.019 rows=5 loops=1)
           ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual time=0.000..0.000 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
   InitPlan 2 (returns $2)
     ->  Aggregate  (cost=0.70..0.71 rows=1 width=0) (actual time=0.029..0.030 rows=1 loops=1)
           ->  CTE Scan on w w_2  (cost=0.00..0.62 rows=31 width=0) (actual time=0.005..0.025 rows=5 loops=1)
   ->  CTE Scan on w  (cost=0.00..0.62 rows=31 width=4) (actual time=0.000..0.002 rows=5 loops=1)
*/
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.