Как SQL Server рассматривает индексы на таблице позади представления?

Таким образом, я пытаюсь понять, как SQL Server использует индексы на таблицах позади представлений. Вот сценарий: Таблица A имеет составной кластерный индекс на полях 1 и 2 и некластеризованный индекс на полях 3 и 4.

Представление A записано против Таблицы A для отфильтровывания дополнительных полей, но поля 1-4 являются частью представления. Таким образом, мы пишем запрос, который соединяет представление с другой таблицей на некластеризованных индексных полях.

Получающийся план запросов совершает нападки, Таблица A со сканированием кластерного индекса (вместо ожидаемого некластеризованного индекса ищут). Однако, если мы заменяем представление в ИЗ пункта с таблицей, план запросов затем поражает некластеризованный индекс, и мы добираемся, индекс ищут, мы ожидали.

Разве механизм SQL не должен использовать индекс на таблице, на которой создается представление? Так как это не делает, почему нет?

9
задан John Saunders 22 July 2010 в 23:42
поделиться

1 ответ

Когда вы думаете о нематериализованных представлениях и оптимизации, думайте о них так:

Движок "вырезает и вставляет" текст представления в каждый запрос, который вы выполняете.

Хорошо, это не совсем 100% правда, но это, вероятно, самый полезный способ представить себе, что можно ожидать в плане производительности.

Однако представления могут быть сложными. Люди склонны думать, что если столбец находится в представлении, то это означает что-то значительное, когда речь идет о производительности запроса. На самом деле, если запрос, использующий ваше представление, не включает набор столбцов, его можно "оптимизировать". Так, если вы выберете все столбцы из ваших базовых таблиц в представлении, а затем выберете только один или два столбца при фактическом использовании представления, запрос будет оптимизирован с учетом только этих двух выбранных столбцов.

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

Widget
-------
ID (UNIQUE)
Name
Price
WidgetTypeID (FK to WidgetType.ID)

WidgetType
----------
ID (UNIQUE)
Name

vw_Widgets
----------
SELECT w.ID, w.Name, w.Price, w.WidgetTypeID, wt.Name AS TypeName
FROM Widgets w
LEFT JOIN WidgetType wt
   ON wt.ID = w.WidgetTypeID;

Обратите внимание на LEFT JOIN в определении представления. Если бы вы просто SELECT Name, Price FROM vw_Widgets, вы бы заметили, что WidgetType даже не был включен в план запроса! Он полностью оптимизирован! Это работает с LEFT JOINS по уникальным столбцам, потому что оптимизатор знает, что поскольку ID WidgetType является UNIQUE, он не создаст никаких дублирующих строк в результате объединения. А поскольку есть FK, вы знаете, что можете оставить соединение как LEFT-соединение, потому что у вас всегда будет соответствующая строка.

Итак, мораль этой истории с представлениями такова: в конце дня важны столбцы, которые вы выбираете, а не столбцы в представлении. Представления не оптимизируются при их создании - они оптимизируются при их использовании.

Ваш вопрос не совсем о представлениях

Ваш вопрос на самом деле более общий - почему вы не можете использовать индекс NC? Я не могу сказать вам точно, потому что не вижу вашей схемы или конкретного запроса, но достаточно сказать, что в определенный момент оптимизатор видит, что стоимость поиска дополнительных полей перевешивает стоимость сканирования таблицы (потому что поиск дорог) и игнорирует ваш некластеризованный индекс.

6
ответ дан 4 December 2019 в 23:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: