Sichtauflösung
Der SQL Server 2005-Abfrageprozessor behandelt indizierte und nicht indizierte Sichten unterschiedlich:
- Die Zeilen einer indizierten Sicht werden in der Datenbank in demselben Format wie eine Tabelle gespeichert. Wenn sich der Abfrageoptimierer entscheidet, eine indizierte Sicht in einem Abfrageplan zu verwenden, wird die indizierte Sicht auf die gleiche Weise wie eine Basistabelle behandelt.
- Nur die Definition einer nicht indizierten Sicht wird gespeichert, nicht die Zeilen der Sicht. Der Abfrageoptimierer nimmt die Logik aus der Sichtdefinition in den Ausführungsplan auf, den er für die SQL-Anweisung erstellt, die auf die nicht indizierte Sicht verweist.
Die Logik, anhand derer der SQL Server-Abfrageoptimierer entscheidet, wann eine indizierte Sicht verwendet werden soll, ist mit der Logik vergleichbar, anhand derer ermittelt wird, wann ein Index für eine Tabelle verwendet wird. Wenn die Daten in der indizierten Sicht die gesamte oder einen Teil der SQL-Anweisung erfüllen und der Abfrageoptimierer ermittelt, dass ein Index für die Sicht der Zugriffspfad mit den geringsten Kosten ist, wählt der Abfrageoptimierer den Index unabhängig davon aus, ob im Namen der Abfrage auf die Sicht verwiesen wird. Weitere Informationen finden Sie unter Auflösen von Indizes für Sichten.
Wenn eine SQL-Anweisung auf eine nicht indizierte Sicht verweist, analysieren der Parser und der Abfrageoptimierer die Quelle sowohl der SQL-Anweisung als auch der Sicht und lösen sie dann zu einem einzigen Ausführungsplan auf. Es gibt nicht einen Plan für die SQL-Anweisung und einen weiteren Plan für die Sicht.
Nehmen Sie z. B. an, dass die folgende Sicht verwendet wird:
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
Von dieser Sicht ausgehend führen die beiden folgenden SQL-Anweisungen dieselben Operationen für die Basistabellen aus und erstellen identische Resultsets:
/* 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';
Durch das SQL Server Management Studio-Showplanfeature wird deutlich, dass das relationale Modul für beide SELECT-Anweisungen denselben Ausführungsplan erstellt.
Verwenden von Hinweisen mit Sichten
Hinweise, die für Sichten in einer Abfrage gespeichert werden, können zu Konflikten mit anderen Hinweisen führen, die beim Erweitern der Sicht für den Zugriff auf ihre Basistabellen erkannt werden. Wenn dieser Fall eintritt, gibt die Abfrage einen Fehler zurück. Angenommen, die folgende Sicht enthält einen Tabellenhinweis in ihrer Definition:
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
Nehmen Sie nun an, dass die folgende Abfrage eingegeben wird:
SELECT AddressID, AddressLine1, StateProvinceCode, CountryRegionCode
FROM Person.AddrState WITH (SERIALIZABLE)
WHERE StateProvinceCode = 'WA'
Die Abfrage erzeugt einen Fehler, weil der SERIALIZABLE-Hinweis, der für die Person.AddrState-Sicht in der Abfrage angewendet wird, an die beiden Tabellen Person.Address und Person.StateProvince in der Sicht weitergegeben wird, wenn diese erweitert wird. Das Erweitern der Sicht legt jedoch außerdem den NOLOCK-Hinweis für Person.Address offen. Da die SERIALIZABLE- und NOLOCK-Hinweise einen Konflikt verursachen, ist die sich ergebende Abfrage falsch.
Die PAGLOCK-, NOLOCK-, ROWLOCK-, TABLOCK- und TABLOCKX-Tabellenhinweise stehen miteinander in Konflikt, ebenso wie die HOLDLOCK-, NOLOCK-, READCOMMITTED-, REPEATABLEREAD- und SERIALIZABLE-Tabellenhinweise.
Hinweise können über die Ebenen geschachtelter Sichten weitergegeben werden. Angenommen, eine Abfrage wendet den HOLDLOCK-Hinweis auf eine Sicht v1 an. Wenn v1 erweitert wird, wird erkennbar, dass die Sicht v2 Teil ihrer Definition ist. Die Definition von v2 enthält einen NOLOCK-Hinweis für eine der Basistabellen der Sicht. Diese Tabelle erbt jedoch außerdem den HOLDLOCK-Hinweis für Sicht v1 von der Abfrage. Da die NOLOCK- und HOLDLOCK-Hinweise einen Konflikt verursachen, führt die Abfrage zu einem Fehler.
Wenn der FORCE ORDER-Hinweis in einer Abfrage verwendet wird, die eine Sicht enthält, wird die Verknüpfungsreihenfolge der Tabellen innerhalb der Sicht durch die Position der Sicht im sortierten Konstrukt festgelegt. Die folgende Abfrage trifft z. B. eine Auswahl aus drei Tabellen und einer Sicht:
SELECT * FROM Table1, Table2, View1, Table3
WHERE Table1.Col1 = Table2.Col1
AND Table2.Col1 = View1.Col1
AND View1.Col2 = Table3.Col2
OPTION (FORCE ORDER)
Außerdem ist View1 wie im folgenden Beispiel gezeigt definiert:
CREATE VIEW View1 AS
SELECT Colx, Coly FROM TableA, TableB
WHERE TableA.ColZ = TableB.Colz
Die Verknüpfungsreihenfolge im Abfrageplan lautet Table1, Table2, TableA, TableB, Table3.
Siehe auch
Konzepte
Auflösen von Indizes für Sichten
Entwerfen und Implementieren von Sichten