Разрешение представлений

Обработчик запросов SQL Server обращается с индексированными и неиндексированными представлениями по-разному:

  • Строки индексированного представления хранятся в базе данных в том же формате, что и таблица. Если оптимизатор запросов решает использовать индексированное представление в плане запроса, оно обрабатывается так же, как базовая таблица.

  • В случае неиндексированного представления хранится только его определение, но не строки. Оптимизатор запросов интегрирует логику определения представления в план выполнения, создаваемый для инструкции SQL, ссылающейся на неиндексированное представление.

Решение об использовании индексированного представления принимается оптимизатором запросов SQL Server на основе тех же принципов, что и решение об использовании индекса таблицы. Если данные индексированного представления охватывают всю инструкцию SQL или ее часть, а оптимизатор запросов определит, что использовать индекс представления выгодно, он выберет индекс независимо от того, имеется ли в запросе ссылка на представление по его имени. Дополнительные сведения см. в разделе Разрешение индексов для представлений.

Если инструкция SQL ссылается на неиндексированное представление, средство синтаксического анализа и оптимизатор запросов анализируют исходный код инструкции SQL и представления, разрешая их в один план выполнения. Отдельных планов для инструкции SQL и представления нет.

Рассмотрим следующее представление:

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

Обе следующие инструкции SQL, основанные на данном представлении, выполняют одни и те же операции над базовой таблицей, формируя одинаковый результат:

/* 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 > '20020531';

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

Используя входящее в среду SQL Server Management Studio средство отображения планов, нужно убедиться, что для обеих этих инструкций SELECT ядро СУБД создает один и тот же план выполнения.

Использование подсказок с представлениями

Подсказки, связываемые с представлениями в запросах, могут конфликтовать с другими подсказками, которые обнаруживаются при расширении представления для доступа к его базовым таблицам. Когда это происходит, запрос возвращает ошибку. Взгляните, например, на следующее представление, в определение которого входит табличная подсказка:

USE AdventureWorks;
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.