2011-09-23 9 views
10

la documentazione per Pg's Window function say:Postgres invierà una clausola WHERE in una VISTA con una funzione Window (Aggregate)?

Le righe considerate da una funzione di finestra sono quelli del "tavolo virtuale" prodotta dalla query clausola FROM come filtrato dalle sue clausole WHERE, GROUP BY, e avere eventuali. Ad esempio, una riga rimossa perché non soddisfa la condizione WHERE non è vista da nessuna funzione della finestra. Una query può contenere più funzioni della finestra che suddividono i dati in diversi modi mediante diverse clausole OVER, ma agiscono tutti sullo stesso insieme di righe definito da questa tabella virtuale.

Tuttavia, non sto vedendo questo. Mi sembra che il filtro di selezione sia molto vicino al margine sinistro e alla parte superiore (ultima cosa fatta).

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

Questi due WindowAgg di essenzialmente modificare il piano per qualcosa che sembra non finire dalla molto più veloce

                 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) 

Che cosa sta succedendo, e come posso risolvere il problema? Sto usando Postgresql 8.4.8. Ecco ciò che la vista reale sta facendo:

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

Siamo spiacenti, non vedo una funzione finestra nella query. C'è una VISTA coinvolta? Si prega di aggiungere la pertinente tabella/vista/definizioni dell'indice. – wildplasser

+0

Sì, ho incollato il contenuto della vista ora. –

+1

Questo è in realtà ciò che sta accadendo. Postgres non sta proponendo la clausola 'WHERE' all'interno della vista, prima di eseguire la funzione della finestra. Interessante. –

risposta

3

No, PostgreSQL solo spingere verso il basso una clausola WHERE su una visione che non dispone di un aggregato. (Le funzioni della finestra sono considerate Aggregati).

< x> penso che è solo una limitazione di implementazione

< EvanCarroll> x: Mi chiedo che cosa avrebbe dovuto essere fatto per spingere il clausola WHERE nel presente caso.

< EvanCarroll> il pianificatore dovrebbe sapere che WindowAgg non aggiunge essa stessa selettività e quindi è sicuro spingere il WHERE verso il basso?

< x> EvanCarroll; un sacco di lavoro molto complicato con il pianificatore, sarei presumo

E,

< a> EvanCarroll: no. una condizione di filtro su una vista si applica al uscita della vista e solo viene spinto verso il basso se la vista non comporta aggregati

+0

.. che ha senso, perché può cambiare il risultato. Questo è molto simile alla differenza tra "DOVE" e "HAVING". –

+0

Sì, ma in questo caso non lo sarebbe.Mi sembra anche che una funzione Window sia leggermente allungata. Non riesco a pensare in ogni caso che una funzione Window non referenziata può cambiare il risultato se WHERE è stato premuto. –

+0

Sembra che ci sia il potenziale per alcune intelligenti ottimizzazioni. Nel frattempo, dovrai buttare giù la clausola WHERE. Se hai bisogno di un modulo generalizzato, puoi ricorrere alle stored procedure. Avresti bisogno di un esempio? –

Problemi correlati