Разрешение представлений
Обработчик запросов SQL Server обращается с индексированными и неиндексированными представлениями по-разному:
Строки индексированного представления хранятся в базе данных в том же формате, что и таблица. Если оптимизатор запросов решает использовать индексированное представление в плане запроса, оно обрабатывается так же, как базовая таблица.
В случае неиндексированного представления хранится только его определение, но не строки. Оптимизатор запросов интегрирует логику определения представления в план выполнения, создаваемый для инструкции SQL, ссылающейся на неиндексированное представление.
Решение об использовании индексированного представления принимается оптимизатором запросов SQL Server на основе тех же принципов, что и решение об использовании индекса таблицы. Если данные индексированного представления охватывают всю инструкцию SQL или ее часть, а оптимизатор запросов определит, что использовать индекс представления выгодно, он выберет индекс независимо от того, имеется ли в запросе ссылка на представление по его имени. Дополнительные сведения см. в разделе Разрешение индексов для представлений.
Если инструкция SQL ссылается на неиндексированное представление, средство синтаксического анализа и оптимизатор запросов анализируют исходный код инструкции SQL и представления, разрешая их в один план выполнения. Отдельных планов для инструкции SQL и представления нет.
Рассмотрим следующее представление:
USE AdventureWorks2008R2;
GO
CREATE VIEW EmployeeName AS
SELECT h.BusinessEntityID, p.LastName, p.FirstName
FROM HumanResources.Employee AS h
JOIN Person.Person AS p
ON h.BusinessEntityID = p.BusinessEntityID;
GO
Обе следующих инструкции SQL, основанных на данном представлении, выполняют одни и те же операции над базовой таблицей, формируя одинаковый результат:
/* SELECT referencing the EmployeeName view. */
SELECT LastName AS EmployeeLastName, SalesOrderID, OrderDate
FROM AdventureWorks2008R2.Sales.SalesOrderHeader AS soh
JOIN AdventureWorks2008R2.dbo.EmployeeName AS EmpN
ON (soh.SalesPersonID = EmpN.BusinessEntityID)
WHERE OrderDate > '20020531';
/* SELECT referencing the Person and Employee tables directly. */
SELECT LastName AS EmployeeLastName, SalesOrderID, OrderDate
FROM AdventureWorks2008R2.HumanResources.Employee AS e
JOIN AdventureWorks2008R2.Sales.SalesOrderHeader AS soh
ON soh.SalesPersonID = e.BusinessEntityID
JOIN AdventureWorks2008R2.Person.Person AS p
ON e.BusinessEntityID =p.BusinessEntityID
WHERE OrderDate > '20020531';
Используя входящее в среду Среда SQL Server Management Studio средство отображения планов Showplan, нужно убедиться, что для обеих этих инструкций SELECT ядро СУБД создает один и тот же план выполнения.
Использование подсказок с представлениями
Подсказки, связываемые с представлениями в запросах, могут конфликтовать с другими подсказками, которые обнаруживаются при расширении представления для доступа к его базовым таблицам. Когда это происходит, запрос возвращает ошибку. Взгляните, например, на следующее представление, в определение которого входит табличная подсказка:
USE AdventureWorks2008R2;
GO
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;
Предположим, что вводится следующий запрос:
SELECT AddressID, AddressLine1, StateProvinceCode, CountryRegionCode
FROM Person.AddrState WITH (SERIALIZABLE)
WHERE StateProvinceCode = 'WA';
Он завершится ошибкой, поскольку подсказка SERIALIZABLE, примененная в запросе к представлению Person.AddrState, при расширении представления распространится как на таблицу Person.Address, так и на таблицу Person.StateProvince. Однако при расширении представления будет также обнаружена подсказка NOLOCK, связанная с таблицей Person.Address. Из-за конфликта подсказок SERIALIZABLE и NOLOCK итоговый запрос окажется неправильным.
Между собой конфликтуют табличные подсказки PAGLOCK, NOLOCK, ROWLOCK, TABLOCK и TABLOCKX, а также табличные подсказки HOLDLOCK, NOLOCK, READCOMMITTED, REPEATABLEREAD и SERIALIZABLE.
Подсказки могут распространяться через уровни вложенных представлений. Предположим, что в запросе подсказка HOLDLOCK применяется к представлению v1. При расширении представления v1 выясняется, что представление v2 является частью его определения. Определение представления v2 включает связанную с одной из его базовых таблиц подсказку NOLOCK. Однако эта таблица также наследует указанную в запросе подсказку HOLDLOCK, примененную к представлению v1. Из-за конфликта подсказок NOLOCK и HOLDLOCK запрос завершится ошибкой.
Если в запросе, включающем представление, используется подсказка FORCE ORDER, порядок соединения таблиц в представлении определяется по позиции представления в конструкции упорядочения. Например, приведенный ниже запрос выбирает данные из трех таблиц и представления:
SELECT * FROM Table1, Table2, View1, Table3
WHERE Table1.Col1 = Table2.Col1
AND Table2.Col1 = View1.Col1
AND View1.Col2 = Table3.Col2;
OPTION (FORCE ORDER)
Допустим, что представление View1 определено следующим образом:
CREATE VIEW View1 AS
SELECT Colx, Coly FROM TableA, TableB
WHERE TableA.ColZ = TableB.Colz;
В этом случае порядок соединения таблиц в плане запроса будет таким: Table1, Table2, TableA, TableB, Table3.
См. также