Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Планы выполнения запросов: предикаты (аргументы) в операторе Index Seek  [new]
Kaiden
Member

Откуда:
Сообщений: 79
Всем привет.

Есть простой теоретический вопрос по планам выполнения запросов. Почему-то не могу накопать на него ответ в мануалах / литературе, если кто-то, подскажет, где про этот момент написано или объяснит своими словами, - буду весьма признателен.

Вопрос в следующем. Есть простейший запрос, соединяющий две таблички (Employee и Address) внутренним соединением и выбирающий из них некоторое количество полей. Есть отбор по одному из полей таблицы Employee. Одна табличка без индексов вообще (Employee), другая (Address) содержит индекс по внешнем ключу, по которому идет соединение (индекс по полю EmployeeID).

SELECT employee.lastName, 
	   address.City
FROM   person.employee INNER JOIN person.address
	   ON employee.EmployeeID = address.EmployeeID
where employee.LastName = 'Иванов'



План запроса тоже простой. СУБД делает table scan по первой табличке по условию из отбора и index seek по второй (по ключу из первой таблицы), затем СУБД "добирает" результат с помощью RID Lookup и "собирает" все в кучу с помощью пары Nested Loops.

Интересует начало плана выполнения запроса - table scan первой таблицы и index seek по второй. Совсем точно - интересует index seek.

У него в аргументах (предикатах) написано следующее:

SEEK:([my_db].[Person].[Address].[EmployeeID]=[my_db].[Person].[Employee].[EmployeeID]) ORDERED FORWARD


В графическом плане выглядит примерно так же, только еще функция scalar operator добавляется после знака равенства.

При этом и в графическом, и в текстовом плане выполнения запроса table scan и index seek находится на одном уровне.

Что физически делает СУБД во время index seek? Все-таки использует ключи из оператора table scan и уже по ним делает поиск? Или просто получает все возможные ключи из первой таблицы и делает поиск по ним, а "отсекает" лишнее уже во время nested loops? Если первое - почему операции находятся на одном уровне в плане, ведь первая должна предшествовать второй, по идее?
17 фев 16, 17:05    [18831079]     Ответить | Цитировать Сообщить модератору
 Re: Планы выполнения запросов: предикаты (аргументы) в операторе Index Seek  [new]
SomewhereSomehow
Member

Откуда: Moscow
Сообщений: 2480
Блог
Kaiden,

Добрый день.

Вопрос в том, как читать план. Если мы читаем графический план в порядке того, как работают операторы, то начинаем слева-направо и сверху-вниз. Если в порядке получения данных, то наоборот. Текстовые планы соответственно сверху-вниз или снизу-вверх с учетом вложенности.

Например:
use tempdb;
go
create table Employee(EmployeeID int, LastName  varchar(8000));
create table [Address](AddressID int, EmployeeID int, City varchar(8000));
create index ix_emplid on [Address](EmployeeID)
insert Employee values(1,'Иванов');
insert [Address] values(1, 1, 'город Москва, 3-я улица Строителей, 25');
update statistics Employee with pagecount = 1000, rowcount = 100000;
update statistics [Address] with pagecount = 1000, rowcount = 100000;
go
set showplan_text on;
go
SELECT employee.lastName, 
	   address.City
FROM   dbo.employee INNER JOIN dbo.address
	   ON employee.EmployeeID = address.EmployeeID
where employee.LastName = 'Иванов'
go
set showplan_text off;
go

Картинка с другого сайта.

Читается соответственно:
1 вызывает 2, 2 вызывает 3, получает строку, 2 вызывает 4, получает строку, 2 соединяет строку из 3 и 4, отдает 1, 1 вызывает 5, соединяет. И т.д. пока не кончатся строки.

На графическом тот же принцип, но немного в другом представлении. Рисовать уже не буду.

Что касается того, где выполняется проверка предиката соединения. У Nested Loops есть две основные стратегии, NL имеет две основные стратегии:
- Nested Loops Join
- Nested Loops Apply (Nested Loops Trivial)

Далее читайте тут, там с картинками и пояснениями, нет хочется повторяться: Вопрос по плану запроса. Nested Loops возвращает лишние строки

П.С.
Планы лучше приводить целиком в формате sqlplan, а не пересказывать словами с выдранными кусочками.
17 фев 16, 18:34    [18831688]     Ответить | Цитировать Сообщить модератору
 Re: Планы выполнения запросов: предикаты (аргументы) в операторе Index Seek  [new]
Kaiden
Member

Откуда:
Сообщений: 79
Спасибо большое за развернутый ответ, теперь стало ясно.
18 фев 16, 08:09    [18833121]     Ответить | Цитировать Сообщить модератору
 Re: Планы выполнения запросов: предикаты (аргументы) в операторе Index Seek  [new]
МуМу
Member

Откуда:
Сообщений: 1134
По моим наблюдения странное поведение планировщика происходит в первую очередь при изменении статистики. Выражается это в том что после пересчета с full scan и очистке хэша планов выполнения запросов ситуация меняется. Но также замечал что видимо сервер анализирует объем доступной(по сегментам) памяти. Выражалось это например при падении счетчика "время жизни страницы"(это скорее всего косвенный счетчик) оптимизатор без видимых причин начинал использовать преимущественно(на определенных типах запросов) нестед лупс вместо хэш джоина. Были мысли эту ситуацию смоделировать но как то лень. Да и главное как мы на это можем повлиять? Гарантированный способ - явно приклеивать xml плана выполнения. Если есть вырожденные случаи в селективности то явно в клиенте анализировать и подкладывать другой план. По моему опыту это не нужно для всех запросов , обычно их набирается 5-10ть на всю систему.
18 фев 16, 12:15    [18834314]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить