sql server 2005 - ¿Por qué poner una cláusula WHERE fuera de vista tiene un rendimiento terrible?
sql-server-2005 tsql (5)
Como solución alternativa, sugeriría usar una función en lugar de una vista para que pueda pasar el parámetro de datos.
Digamos que tienes una vista:
CREATE VIEW dbo.v_SomeJoinedTables AS
SELECT
a.date,
a.Col1,
b.Col2,
DENSE_RANK()
OVER(PARTITION BY a.date, a.Col2 ORDER BY a.Col3) as Something
FROM a JOIN b on a.date = b.date
He encontrado que el rendimiento de:
SELECT *
FROM v_SomeJoinedTables
WHERE date > ''2011-01-01''
es mucho peor que
SELECT *,
DENSE_RANK()
OVER(PARTITION BY a.date, a.Col2 ORDER BY a.Col3) as Something
FROM a JOIN b ON a.date = b.date
WHERE a.date > ''2011-01-01''
Estoy muy sorprendido de que el plan de consulta para estas dos afirmaciones no sea el mismo.
También he intentado usar una función de valor de tabla en línea, pero la consulta todavía tarda 100-1000 veces más que el código donde copio y pego la lógica de vista.
¿Algunas ideas?
La sintaxis de OVER () era nueva en SS2005 y aparentemente no estaba bien integrada en el optimizador. Te sugiero que pruebes una expresión más tradicional? Probablemente NO sea una expresión si te importa la optimización.
http://www.sqlteam.com/article/sql-sever-2005-using-over-with-aggregate-functions
O, mejor, familiarizarse un poco con el generador de perfiles: la vista debería poder corregirse.
No soy un experto en SQL, por lo que se me puede rechazar por mi insensatez, pero supongo que en el primer caso, SQL está obteniendo los resultados de toda la vista antes de aplicar el predicado en la cláusula WHERE. Entonces, cuando consulta la vista, selecciona todos los registros, los coloca en la memoria y luego aplica el filtro de fecha una vez que se realiza.
Esto parece similar a la forma en que se obtiene todo el conjunto de datos especificado en sus combinaciones antes de aplicar el filtro en el DÓNDE (la lección aquí es que debe aplicar predicados en su cláusula ON cuando sea posible).
A menos que las vistas sean tratadas de alguna manera diferente.
Se llama " Predicado empujando " también conocido como filtrado diferido.
SQL Server no siempre se da cuenta de que WHERE se puede aplicar "antes", dentro de la vista de manera efectiva.
Se ha mitigado en SQL Server 2008 para trabajar más como se esperaba
Técnicamente, no estás comparando entre las mismas sentencias de SQL. Su vista indica que devuelve a.date, a.Col1, b.Col2,
más su función DENSE_RANK (). En su consulta sin la vista, devuelve todas las columnas.
Al principio, puedes pensar que devolver todas las columnas sería peor. Pero es difícil determinar cuál sería mejor sin saber cómo se ve la estructura de la tabla, incluidos los índices.
¿Ha comparado los planes de consulta para cada declaración?