Résolution de vues

Le processeur de requêtes SQL Server 2005 traite différemment les vues indexées et les vues non indexées :

  • Les lignes des vues indexées sont stockées dans la base de données dans le même format qu'une table. Si l'optimiseur de requête décide d'utiliser une vue indexée dans un plan de requête, celle-ci est traitée de la même façon qu'une table de base.
  • Seule la définition d'une vue non indexée est stockée, tandis que les lignes de la vue ne le sont pas. L'optimiseur de requête incorpore la logique de la définition de la vue dans le plan d'exécution qu'il construit pour l'instruction SQL faisant référence à la vue non indexée.

La logique utilisée par l'optimiseur de requêtes SQL Server pour déterminer quand utiliser une vue indexée est similaire à la logique employée pour décider quand utiliser un index sur une table. Si les données de la vue indexée couvrent tout ou partie de l'instruction SQL et si l'optimiseur de requête détermine qu'un index sur la vue est le chemin d'accès le moins coûteux, l'optimiseur choisit l'index, que la vue soit référencée ou non par son nom dans la requête. Pour plus d'informations, consultez Résolution d'index sur les vues.

Lorsqu'une instruction SQL fait référence à une vue non indexée, l'analyseur et l'optimiseur de requête analysent la source de l'instruction SQL et de la vue, puis les résolvent dans un même plan d'exécution. Il n'y a pas de plans distincts pour l'instruction SQL et pour la vue.

Imaginons par exemple la vue suivante :

USE AdventureWorks
GO
CREATE VIEW EmployeeName AS
SELECT h.EmployeeID, c.LastName, c.FirstName
FROM HumanResources.Employee h 
JOIN Person.Contact c
ON h.EmployeeID = c.ContactID;
GO

Sur la base de cette vue, les deux instructions SQL exécutent les mêmes opérations sur les tables de base et produisent les mêmes résultats :

/* SELECT referencing the EmployeeName view. */
SELECT LastName AS EmployeeLastName,
    SalesOrderID, OrderDate
FROM AdventureWorks.Sales.SalesOrderHeader AS soh
JOIN AdventureWorks.dbo.EmployeeName as EmpN
ON (soh.ContactID = EmpN.EmployeeID)
WHERE OrderDate > '31 May, 2002';

/* SELECT referencing the Contact and Employee tables directly. */
SELECT LastName AS EmployeeLastName,
    SalesOrderID, OrderDate
FROM AdventureWorks.Sales.SalesOrderHeader AS soh
 JOIN AdventureWorks.Person.Contact as c
 ON soh.ContactID = c.ContactID
JOIN AdventureWorks.HumanResources.Employee as e
ON e.EmployeeID =c.ContactID
WHERE OrderDate > '31 May, 2002';

La fonctionnalité Showplan de SQL Server Management Studio montre que le moteur relationnel crée le même plan d'exécution pour ces deux instructions SELECT.

Utilisation d'indicateurs avec les vues

Les indicateurs placés sur une vue dans une requête peuvent être en conflit avec d'autres indicateurs découverts lors du développement de la vue pour l'accès à ses tables de base. Dans ce cas, la requête renvoie une erreur. Imaginons par exemple la vue suivante, dont la définition contient un indicateur de table :

USE AdventureWorks
CREATE VIEW Person.AddrState WITH SCHEMABINDING AS
SELECT a.AddressID, a.AddressLine1, 
    s.StateProvinceCode, s.CountryRegionCode
FROM Person.Address a WITH (NOLOCK), Person.StateProvince s
WHERE a.StateProvinceID = s.StateProvinceID

Supposons à présent cette requête :

SELECT AddressID, AddressLine1, StateProvinceCode, CountryRegionCode
FROM Person.AddrState WITH (SERIALIZABLE)
WHERE StateProvinceCode = 'WA'

La requête échoue, parce que l'indicateur SERIALIZABLE appliqué à la vue Person.AddrState de la requête est propagé dans les tables Person.Address et Person.StateProvince de la vue lorsque cette dernière est développée. Ce développement révèle en outre l'indicateur NOLOCK sur Person.Address. La requête résultante est incorrecte parce que les indicateurs SERIALIZABLE et NOLOCK sont en conflit.

Les indicateurs de table PAGLOCK, NOLOCK, ROWLOCK, TABLOCK et TABLOCKX sont en conflit les uns avec les autres, de même que les indicateurs de table HOLDLOCK, NOLOCK, READCOMMITTED, REPEATABLEREAD et SERIALIZABLE.

Les indicateurs peuvent se propager à différents niveaux des vues imbriquées. Imaginons par exemple une requête qui applique l'indicateur HOLDLOCK sur une vue v1. Quand la vue v1 est développée, la vue v2 apparaît dans sa définition. Et la définition de v2 comprend un indicateur NOLOCK sur l'une de ses tables de base. Cependant, cette table hérite également de l'indicateur HOLDLOCK de la requête sur la vue v1. La requête échoue parce que les indicateurs HOLDLOCK et NOLOCK sont en conflit.

Si l'indicateur FORCE ORDER est utilisé dans une requête contenant une vue, l'ordre de jointure des tables de la vue est déterminé par la position de la vue dans la construction ordonnée. Par exemple, la requête suivante effectue une sélection dans trois tables et une vue :

SELECT * FROM Table1, Table2, View1, Table3
WHERE Table1.Col1 = Table2.Col1 
AND Table2.Col1 = View1.Col1
AND View1.Col2 = Table3.Col2
OPTION (FORCE ORDER)

Et View1 est définie comme suit :

CREATE VIEW View1 AS
SELECT Colx, Coly FROM TableA, TableB
WHERE TableA.ColZ = TableB.Colz

L'ordre de jointure dans le plan de requête plan est : Table1, Table2, TableA, TableB, Table3.

Voir aussi

Concepts

Résolution d'index sur les vues
Conception et mise en œuvre de vues

Aide et Informations

Assistance sur SQL Server 2005