2011-09-23 69 views
10

Pg's Window function say該文檔:Will Postgres將WHERE子句下推到具有窗口函數(Aggregate)的VIEW中?

由窗口函數考慮的行是那些所生產的「虛擬表」,如果任何作爲過濾通過它的WHERE,GROUP BY和HAVING子句的查詢的FROM子句。 例如,由於不符合WHERE條件而被刪除的行不被任何窗口函數看到。查詢可以包含多個窗口函數,這些窗口函數通過不同的OVER子句以不同的方式對數據進行切片,但它們都作用於由此虛擬表定義的同一行集合。

但是,我沒看到這個。在我看來,選擇過濾器非常靠近左邊距和頂部(最後完成的事情)。

=# EXPLAIN SELECT * FROM chrome_nvd.view_options where fkey_style = 303451; 
                 QUERY PLAN              
---------------------------------------------------------------------------------------------------------------------- 
Subquery Scan view_options (cost=2098450.26..2142926.28 rows=14825 width=180) 
    Filter: (view_options.fkey_style = 303451) 
    -> Sort (cost=2098450.26..2105862.93 rows=2965068 width=189) 
     Sort Key: o.sequence 
     -> WindowAgg (cost=1446776.02..1506077.38 rows=2965068 width=189) 
       -> Sort (cost=1446776.02..1454188.69 rows=2965068 width=189) 
        Sort Key: h.name, k.name 
        -> WindowAgg (cost=802514.45..854403.14 rows=2965068 width=189) 
          -> Sort (cost=802514.45..809927.12 rows=2965068 width=189) 
           Sort Key: h.name 
           -> Hash Join (cost=18.52..210141.57 rows=2965068 width=189) 
             Hash Cond: (o.fkey_opt_header = h.id) 
             -> Hash Join (cost=3.72..169357.09 rows=2965068 width=166) 
              Hash Cond: (o.fkey_opt_kind = k.id) 
              -> Seq Scan on options o (cost=0.00..128583.68 rows=2965068 width=156) 
              -> Hash (cost=2.21..2.21 rows=121 width=18) 
                -> Seq Scan on opt_kind k (cost=0.00..2.21 rows=121 width=18) 
             -> Hash (cost=8.80..8.80 rows=480 width=31) 
              -> Seq Scan on opt_header h (cost=0.00..8.80 rows=480 width=31) 
(19 rows) 

這兩個WindowAgg的本質改變計劃的東西,似乎從來沒有從快得多

                 QUERY PLAN                  
-------------------------------------------------------------------------------------------------------------------------------------------------------- 
Subquery Scan view_options (cost=329.47..330.42 rows=76 width=164) (actual time=20.263..20.403 rows=42 loops=1) 
    -> Sort (cost=329.47..329.66 rows=76 width=189) (actual time=20.258..20.300 rows=42 loops=1) 
     Sort Key: o.sequence 
     Sort Method: quicksort Memory: 35kB 
     -> Hash Join (cost=18.52..327.10 rows=76 width=189) (actual time=19.427..19.961 rows=42 loops=1) 
       Hash Cond: (o.fkey_opt_header = h.id) 
       -> Hash Join (cost=3.72..311.25 rows=76 width=166) (actual time=17.679..18.085 rows=42 loops=1) 
        Hash Cond: (o.fkey_opt_kind = k.id) 
        -> Index Scan using options_pkey on options o (cost=0.00..306.48 rows=76 width=156) (actual time=17.152..17.410 rows=42 loops=1) 
          Index Cond: (fkey_style = 303451) 
        -> Hash (cost=2.21..2.21 rows=121 width=18) (actual time=0.432..0.432 rows=121 loops=1) 
          -> Seq Scan on opt_kind k (cost=0.00..2.21 rows=121 width=18) (actual time=0.042..0.196 rows=121 loops=1) 
       -> Hash (cost=8.80..8.80 rows=480 width=31) (actual time=1.687..1.687 rows=480 loops=1) 
        -> Seq Scan on opt_header h (cost=0.00..8.80 rows=480 width=31) (actual time=0.030..0.748 rows=480 loops=1) 
Total runtime: 20.893 ms 
(15 rows) 

這是怎麼回事結束,以及如何解決它?我正在使用Postgresql 8.4.8。這裏是實際的觀點在做什麼:

SELECT o.fkey_style, h.name AS header, k.name AS kind 
    , o.code, o.name AS option_name, o.description 
    , count(*) OVER (PARTITION BY h.name) AS header_count 
    , count(*) OVER (PARTITION BY h.name, k.name) AS header_kind_count 
    FROM chrome_nvd.options o 
    JOIN chrome_nvd.opt_header h ON h.id = o.fkey_opt_header 
    JOIN chrome_nvd.opt_kind k ON k.id = o.fkey_opt_kind 
    ORDER BY o.sequence; 
+1

對不起,我沒有看到在查詢窗口函數。是否有VIEW參與?請添加相關的表/視圖/索引定義。 – wildplasser

+0

是的,我現在粘貼了視圖內容。 –

+1

這實際上是發生了什麼事情。在執行窗口函數之前,Postgres不會傳播視圖內部的WHERE子句。有趣。 –

回答

3

不,PostgreSQL將只下推一個沒有聚合的VIEW的WHERE子句。 (窗口函數被認爲是聚合)。

< X>我認爲這只是一個實施限制

< EvanCarroll> X:我不知道會有什麼工作要做,以推動 WHERE子句在這種情況下。

< EvanCarroll>計劃者必須知道WindowAgg本身不會增加選擇性,因此可以安全地將WHERE降下來?

< x> EvanCarroll;很多與規劃者非常複雜的工作,我會假設

而且,

<一> EvanCarroll:都能跟得上。在視圖過濾條件適用於該視圖的輸出只有被按下,如果認爲不涉及聚集

+0

..這是有道理的,因爲它可以改變結果。這很像「WHERE」和「HAVING」之間的區別。 –

+0

是的,但在這種情況下它不會。在我看來,像Window函數是一個小小的延伸。我無法想象,如果WHERE被推下,未引用的Window函數可以改變結果。 –

+0

看起來像有一些聰明的優化的潛力。與此同時,你將不得不自己按下WHERE子句。如果你需要一個通用表單,你可以使用存儲過程。你需要一個例子嗎? –