Làm cách nào để tôi 'gợi ý' tính chính xác của CTE đệ quy?


10

Tôi đang sử dụng CTE đệ quy sau đây làm ví dụ tối thiểu, nhưng nói chung, trình tối ưu hóa phải sử dụng các số nguyên tố 'đoán' mặc định cho các CTE đệ quy:

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
*/

Lưu ý các hồng y rows=31ước tính và rows=5thực tế trong kế hoạch trên. Trong một số trường hợp, 100 dường như được sử dụng như một ước tính, tôi không chắc logic chính xác đằng sau dự đoán.

Trong vấn đề thế giới thực của tôi, ước tính cardinality kém đang ngăn cản kế hoạch 'vòng lặp lồng nhau' nhanh chóng được chọn. Làm cách nào tôi có thể 'gợi ý' thẻ tối ưu hóa cho CTE đệ quy để giải quyết vấn đề này?


5
Đây là một trong nhiều trường hợp gợi ý thống kê sẽ thực sự tốt đẹp để có. Có COSTchức năng, nhưng không nhiều. Tôi khuyên bạn nên nâng cấp nó trên các tin tặc pssql, nhưng bạn sẽ bị cuốn vào vòng lặp thứ n của cuộc tranh luận "gợi ý", lãng phí khối lượng không khí nóng và không đạt được gì :-(
Craig Ringer

Câu trả lời:


8

Tôi đã giải quyết vấn đề như thế này, nhưng tôi hy vọng có một cách ít gây cười hơn:

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)
*/
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.