2011-09-23 10 views
10

la documentación para Pg's Window function say:¿Postgres presionará una cláusula WHERE en una VISTA con una función de ventana (agregado)?

Las filas considerados por una función de ventana son los de la "mesa virtual", producido por la consulta de cláusula como filtrada por sus cláusulas WHERE, GROUP BY, y tener en su caso. Por ejemplo, una fila eliminada porque no cumple con la condición DONDE no es vista por ninguna función de ventana. Una consulta puede contener varias funciones de ventana que segmentan los datos de diferentes maneras mediante diferentes cláusulas OVER, pero todas actúan sobre la misma colección de filas definidas por esta tabla virtual.

Sin embargo, no estoy viendo esto. Me parece que el filtro de selección está muy cerca del margen izquierdo y arriba (lo último que se hizo).

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

Estos dos esencialmente de cambiar el plan de algo que parece no terminar de la mucho más rápido

                 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) 

Lo que está pasando, y cómo lo arreglo WindowAgg? Estoy usando Postgresql 8.4.8. Aquí es lo que el punto de vista real está haciendo:

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

Lo sentimos, no veo una función de ventana en su consulta. ¿Hay una VISTA involucrada? Agregue las definiciones relevantes de tabla/vista/índice. – wildplasser

+0

Sí, he pegado los contenidos de la vista ahora. –

+1

Eso es realmente lo que está sucediendo. Postgres no está propagando la cláusula 'WHERE' dentro de la vista, antes de ejecutar la función de ventana. Interesante. –

Respuesta

3

No, PostgreSQL sólo empujar hacia abajo una cláusula WHERE en una visión que no tiene un agregado. (Las funciones de ventana se consideran Agregados).

< x> creo que eso es sólo una limitación aplicación

< EvanCarroll> x: Me pregunto qué habría que hacer para empujar el cláusula WHERE en el presente caso.

< EvanCarroll> el planificador debería saber que WindowAgg no agrega selectividad por sí mismo y, por lo tanto, es seguro presionar WHERE hacia abajo?

< x> EvanCarroll; un montón de trabajo muy complicado con el planificador, me gustaría presumir

Y,

< a> EvanCarroll: pues no. una condición de filtro en una vista se aplica a la salida de de la vista y sólo es empujado hacia abajo si la vista no implica agregados

+0

.. que tiene sentido, porque puede cambiar el resultado. Esto es muy parecido a la diferencia entre 'WHERE 'y' HAVING'. –

+0

Sí, pero en este caso no sería así.También me parece que una función de ventana es un poco estirada. No se me ocurre de todos modos una función de ventana no referenciada puede cambiar el resultado si se empujó hacia abajo el DONDE. –

+0

Parece que hay potencial para algunas optimizaciones inteligentes. Mientras tanto, tendrá que presionar la cláusula WHERE usted mismo. Si necesita un formulario generalizado, puede recurrir a procedimientos almacenados. ¿Necesitarías un ejemplo? –

Cuestiones relacionadas