sql >> Base de Datos >  >> RDS >> Sqlserver

¿Por qué el Optimizador de consultas ignora por completo los índices de vista indexados?

tl;dr respuesta:si no especifica NOEXPAND, el optimizador de consultas no tiene idea de que está enviando una selección simple desde una vista. Tendría que hacer coincidir la expansión de su consulta (que es todo lo que ve) con algún índice de vista. Probablemente no se moleste cuando se trata de una unión de cinco vías con un montón de yesos.

Ver la coincidencia de índice con una consulta es un problema difícil, y creo que su vista es demasiado complicada para que el motor de consulta coincida con un índice. Considere esta como una de sus consultas:

SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';

Es obvio para usted que esto puede usar un índice de vista, pero esta no es la consulta que ve el motor de consultas. Las vistas se expanden automáticamente si no especifica NOEXPAND, así que esto es lo que va al motor de consultas:

SELECT ID, Code1 FROM (
    SELECT e.ID, 'NR'+CAST(c1.CODE as nvarchar(11)) as Code1, 'NR'+CAST(c2.CODE as nvarchar(11)) as Code2, 'NR'+CAST(c3.CODE as nvarchar(11)) as Code3, 'NR'+CAST(c4.CODE as nvarchar(11)) as Code4, 'NR'+CAST(c5.CODE as nvarchar(11)) as Code5
    FROM dbo.Entity e
        inner join  dbo.Classificator1 c1 on e.ID = c1.ID
        inner join  dbo.Classificator2 c2 on e.ID = c2.ID
        inner join  dbo.Classificator3 c3 on e.ID = c3.ID
        inner join  dbo.Classificator4 c4 on e.ID = c4.ID
        inner join  dbo.Classificator5 c5 on e.ID = c5.ID;
) AS V;

El motor de consulta ve esta consulta complicada y tiene información (pero probablemente no SQL de definiciones de vista) que describe los índices de vista que se han definido. Dado que esta consulta y los índices de vista tienen múltiples uniones y conversiones, la coincidencia es un trabajo difícil.

Tenga en cuenta que sabe que las uniones y las coincidencias son idénticas en esta consulta y en los índices de vista, pero el procesador de consultas no lo sabe. Trata esta consulta de la misma manera que si uniera cinco copias de Classificator3, o si una de las columnas fuera 'NQ'+CAST(c2.CODE as varchar(12)). El comparador de índices de vista (suponiendo que intentara hacer coincidir una consulta tan complicada) tendría que hacer coincidir cada detalle de esta consulta con los detalles de los índices de vista en las tablas involucradas.

El motor de consultas tiene como objetivo n.º 1 encontrar una manera de ejecutar la consulta de manera eficiente. Probablemente no esté diseñado para pasar mucho tiempo tratando de hacer coincidir cada detalle de una unión de cinco vías y CAST con un índice de visualización.

Si tuviera que adivinar, sospecho que el comparador de índices de vista ve que las columnas de resultados de la consulta ni siquiera son columnas de ninguna tabla subyacente (debido al CAST) y simplemente no se molesta en intentar nada. Añadido :Me equivoco. Acabo de probar la sugerencia de Martin de actualizar las estadísticas para hacer que la consulta sea costosa, y se comparó un índice de vista para algunas de estas consultas sin NOEXPAND. ¡El comparador de vistas es más inteligente de lo que pensaba! Entonces, el problema es que el comparador de vistas probablemente se esfuerce más por hacer coincidir una consulta complicada si su costo es muy alto.

Use la sugerencia NOEXPAND en lugar de esperar que el motor de consultas pueda averiguar qué coincide aquí. NOEXPAND es absolutamente tu amigo, porque entonces el motor de consulta puede ver

SELECT ID, Code1 FROM EntityView Where Code1 > 'NR%';

y luego es inmediatamente obvio para el comparador de índices de vista que hay un índice útil.

(Nota:su código SQL Fiddle tiene las 5 referencias de clave externa a la misma tabla, lo que probablemente no sea lo que desea).