Risoluzione delle viste
In Query Processor di SQL Server 2005 le viste indicizzate e non indicizzate vengono gestite in modi diversi:
- Le righe di una vista indicizzata vengono archiviate nel database con lo stesso formato di una tabella. Se Query Optimizer decide di utilizzare una vista indicizzata in un piano di query, la vista indicizzata verrà gestita come una tabella di base.
- Viene archiviata solo la definizione di una vista indicizzata e non le righe della vista. Query Optimizer incorpora la logica della definizione della vista nel piano di esecuzione creato per l'istruzione SQL che fa riferimento alla vista non indicizzata.
La logica utilizzata da Query Optimizer di SQL Server per decidere quando utilizzare una vista indicizzata è analoga alla logica utilizzata per decidere quando utilizzare un indice per una tabella. Se i dati della vista indicizzata coprono tutta o parte dell'istruzione SQL e Query Optimizer identifica un indice della vista come percorso di accesso più economico, tale indice verrà scelto indipendentemente dal fatto che nella query venga fatto o meno riferimento alla vista in questione. Per ulteriori informazioni, vedere Risoluzione di indici nelle viste.
Se un'istruzione SQL fa riferimento a una vista non indicizzata, il parser e Query Optimizer analizzano le origini dell'istruzione SQL e della vista e le risolvono in un singolo piano di esecuzione. Il piano di esecuzione è lo stesso per l'istruzione SQL e per la vista.
Si consideri, ad esempio, la vista seguente:
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
In base a questa vista le due istruzioni SQL seguenti eseguono le stesse operazioni sulle tabelle di base e producono gli stessi risultati:
/* 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 funzionalità Showplan di SQL Server Management Studio indica che il motore relazionale crea lo stesso piano di esecuzione per entrambe le istruzioni SELECT.
Utilizzo di hint con le viste
Gli hint inseriti nelle viste di una query possono entrare in conflitto con altri hint rilevati quando la vista viene espansa in modo da accedere alle relative tabelle di base. In tali circostanze la query restituisce un errore. Si consideri, ad esempio, la vista seguente nella cui definizione è contenuto un hint di tabella:
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
Si supponga a questo punto di immettere la query seguente:
SELECT AddressID, AddressLine1, StateProvinceCode, CountryRegionCode
FROM Person.AddrState WITH (SERIALIZABLE)
WHERE StateProvinceCode = 'WA'
La query ha esito negativo perché l'hint SERIALIZABLE applicato nella vista Person.AddrState della query viene propagato a entrambe le tabelle Person.Address e Person.StateProvince quando la vista viene espansa. L'espansione della vista consente inoltre di rilevare l'hint NOLOCK nella tabella Person.Address. Gli hint SERIALIZABLE e NOLOCK sono in conflitto tra loro, pertanto la query risultante non è corretta.
Gli hint di tabella PAGLOCK, NOLOCK, ROWLOCK, TABLOCK o TABLOCKX sono in conflitto tra loro, così come HOLDLOCK, NOLOCK, READCOMMITTED, REPEATABLEREAD, SERIALIZABLE.
Gli hint possono propagarsi in più livelli di viste nidificate. Si supponga, ad esempio, una query che applica l'hint HOLDLOCK in una vista v1. Espandendo v1, si noterà che la definizione di tale vista include la vista v2, la cui definizione include a sua volta un hint NOLOCK in una delle tabelle di base. Tale tabella eredita inoltre l'hint HOLDLOCK dalla query sulla vista v1. Gli hint NOLOCK e HOLDLOCK sono in conflitto tra loro, pertanto la query ha esito negativo.
Quando si utilizza l'hint FORCE ORDER in una query che contiene una vista, l'ordine di join delle tabelle all'interno della vista dipende dalla posizione della vista nel costrutto ordinato. La query seguente, ad esempio, consente di selezionare da tre tabelle e una vista:
SELECT * FROM Table1, Table2, View1, Table3
WHERE Table1.Col1 = Table2.Col1
AND Table2.Col1 = View1.Col1
AND View1.Col2 = Table3.Col2
OPTION (FORCE ORDER)
La vista View1 viene definita come illustrato di seguito:
CREATE VIEW View1 AS
SELECT Colx, Coly FROM TableA, TableB
WHERE TableA.ColZ = TableB.Colz
L'ordine di join nel piano di query sarà quindi Table1, Table2, TableA, TableB, Table3.
Vedere anche
Concetti
Risoluzione di indici nelle viste
Progettazione e implementazione di viste