Автор: Craig Freedman Scans vs. Seeks
Scan и Seek — это итераторы, которые SQL Server использует для чтения данных из таблиц и индексов. Эти итераторы являются одними из самых фундаментальных, которые можно встретить почти в каждом в плане запроса. Так в чем разница между Scan (просмотром) и Seek (поиском)?
Просмотр возвращает всю таблицу или индекс. Поиск возвращает строки из одного или нескольких диапазонов индекса на основе предиката. Например, рассмотрим следующий запрос:
select OrderDate from Orders where OrderKey = 2
Просмотр
При просмотре мы считываем каждую строку из таблицы Orders, оцениваем предикат «where OrderKey = 2» и, если предикат истинен (т. е. если
строка соответствует требованиям), возвращаем эту строку. В таком случае мы
называем предикат «residual (остаточным)» предикатом. В целях повышения производительности, мы
оцениваем остаточный предикат при просмотре только по возможности. Однако, если
такой предикат слишком затратен, мы можем применить его отдельно, в итераторе
фильтра. Остаточный предикат появляется в текстовом представлении плана после
ключевого слова WHERE, а в XML-представлении плана с тегом <Predicate>.
Вот текстовое представление плана (слегка
отредактированное для краткости) нашего запроса, где наблюдаем просмотр:
|--Table
Scan(OBJECT:([ORDERS]), WHERE:([ORDERKEY]=(2)))
Следующий рисунок иллюстрирует просмотр:
Поскольку просмотр затрагивает все строки таблицы, независимо от того, соответствует она предикату или нет, стоимость плана пропорциональна общему количеству строк в таблице. Таким образом, просмотр является эффективной стратегией, если таблица небольшая или если большинство строк соответствуют предикату. Однако, если таблица большая или большинство строк не соответствуют предикату, будет затронуто гораздо больше страниц и строк, а значит выполнено чересчур много операций ввода-вывода.
Поиск
Вернёмся к нашему примеру, если у нас есть индекс по OrderKey, лучшим планом может быть Поиск (seek). При поиске мы используем индекс для прямого
перехода к тем строкам, которые удовлетворяют предикату. В этом случае мы
называем предикат «Поисковым» предикатом. В большинстве случаев нам не нужно
повторно оценивать поисковый предикат как остаточный предикат. Индекс
гарантирует, что поиск возвращает только те строки, которые соответствуют
требованиям. Поисковый предикат показан в текстовом представлении плана с
ключевым словом SEEK, а в XML представлении с тегом <SeekPredicates>.
Вот текстовый план для того же запроса с
использованием поиска:
|--Index
Seek(OBJECT:([ORDERS].[OKEY_IDX]), SEEK:([ORDERKEY]=(2)) ORDERED FORWARD)
Следующий рисунок иллюстрирует поиск:
Поскольку поиск касается только строк, которые соответствуют условию предиката, и содержащих их страниц, стоимость плана будет пропорциональна количеству выбранных предикатом строк и страниц, а не числу строк в таблице. Поэтому поиск, как правило, является более эффективной стратегией, если у нас есть высокоселективный предикат поиска; то есть если у нас есть предикат поиска, который исключает большую часть таблицы.Примечание о представлении плана
В планах запросов вы можете увидеть просмотр и поиск по индексу, а также по куче (объект без индекса) или кластерному индексу. В таблице ниже показаны все допустимые комбинации:
|
Scan |
Seek |
Heap |
Table Scan |
|
Clustered Index |
Clustered Index Scan |
Clustered Index Seek |
Non-clustered Index |
Index Scan |
Index Seek |
Комментариев нет:
Отправить комментарий