2011-09-23 7 views
10

Docs do Pg's Window function say:Czy Postgres wrzuci klauzulę WHERE do WIDOKU z funkcją okna (Agregat)?

Rzędy uznane przez funkcję okna są związki o „wirtualnego tabeli” produkowanej przez kwerendy FROM przesączeniu jej klauzule GDZIE pogrupować według oraz posiadające jeśli występują. Na przykład wiersz usunięty, ponieważ nie spełnia warunku WHERE, nie jest widoczny dla żadnej funkcji okna. Kwerenda może zawierać wiele funkcji okna, które dzielą dane na różne sposoby za pomocą różnych klauzul OVER, ale wszystkie działają na tym samym zbiorze wierszy zdefiniowanym przez tę wirtualną tabelę.

Jednak nie widzę tego. Wydaje mi się, że filtr wyboru jest bardzo blisko lewego marginesu i góry (ostatnia rzecz wykonana).

=# 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) 

Te dwa WindowAgg na zasadniczo zmienić plan na coś, co wydaje się nigdy nie skończyć z znacznie szybciej

                 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) 

Co się dzieje i jak to naprawić? Używam PostgreSQL 8.4.8. Oto co rzeczywisty widok robi:

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

Niestety, nie widzę funkcji okna w zapytaniu. Czy jest zaangażowany WIDOK? Dodaj odpowiednie definicje tabeli/widoku/indeksu. – wildplasser

+0

Tak, teraz wkleiłem zawartość widoku. –

+1

Tak naprawdę to się dzieje. Postgres nie propaguje klauzuli "WHERE" wewnątrz widoku przed wykonaniem funkcji okna. Ciekawy. –

Odpowiedz

3

Nie, PostgreSQL będzie naciskać tylko w dół klauzuli WHERE na pogląd, że nie ma agregatu. (Funkcje okna są traktowane jako agregaty).

< x> Myślę, że to po prostu ograniczenie realizacja

< EvanCarroll> x: Zastanawiam się, co musiałby zrobić, by pchnąć WHERE w niniejszej sprawie.

< EvanCarroll> planista musiałby wiedzieć, że WindowAgg sam nie dodaje selektywności i dlatego można bezpiecznie zgasić GDZIE?

< x> EvanCarroll; wiele bardzo skomplikowanej pracy z planowania, będę zakładać

, a

< a> EvanCarroll: Nie. Warunkiem filtr na widoku dotyczy wyjścia widoku i tylko zostaje wepchnięty jeśli widok nie obejmuje agregaty

+0

.. co ma sens, ponieważ może zmienić wynik. Jest to bardzo podobne do różnicy między "WHERE" i "HAVING". –

+0

Tak, ale w tym przypadku nie.Wydaje mi się również, że funkcja okna jest lekkim rozciągnięciem. I tak nie mogę myśleć, że nieodwołalna funkcja okna może zmienić wynik, jeśli GDZIE został zepchnięty. –

+0

Wygląda na to, że istnieje potencjał do sprytnych optymalizacji. W międzyczasie będziesz musiał samodzielnie zrzucić klauzulę WHERE. Jeśli potrzebujesz uogólnionego formularza, możesz skorzystać z procedur składowanych. Czy potrzebujesz przykładu? –