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

Откуда:
Сообщений: 5
Имеется следующая таблица:
create table dbo.Customer
(
	CustomerId   int identity not null,
	CustomerName varchar(100) not null,
	constraint PK_Customer primary key (CustomerId)
);
create table dbo.[Order]
(
	CustomerId  int  not null,
	OrderId     int  not null,
	OrderDate   date not null default sysdatetime(),
	Prepayment  real not null default 0,
	TotalSum    real not null default 0,
	TotalDebt   real not null default 0,
	Postponed   bit  not null default 0,
	constraint PK_Order primary key nonclustered (OrderId),
	index IX_Order_CustomerId clustered (CustomerId),
	constraint FK_Order_CustomerId foreign key (CustomerId) references dbo.Customer (CustomerId)
);
--вставляем данные
insert into dbo.Customer values ('LLC CarFirm');
insert into dbo.CustomerPhone values (1, '555-55-55');
insert into dbo.[Order] values (1, 1, sysdatetime(), 100, default, default, default);
--запрос
select c.CustomerName [CustomerName], o.TotalSum [Total Sum], o.Postponed [Is Postponed]
from dbo.[Order] o
	inner join dbo.Customer c
	on o.CustomerId = c.CustomerId;

Получаем вот такой план:
Картинка с другого сайта.


Вопрос - почему используется Index Scan вместо Index Seek?
13 мар 17, 21:51    [20291410]     Ответить | Цитировать Сообщить модератору
 Re: Index Scan в плане  [new]
invm
Member

Откуда: Москва
Сообщений: 9646
Seek - поиск по ключу.
По какому ключу вы собрались искать в Order?
13 мар 17, 21:57    [20291440]     Ответить | Цитировать Сообщить модератору
 Re: Index Scan в плане  [new]
ZeroFrost
Member

Откуда:
Сообщений: 5
@invm
Меня интересует Index Scan IX_Order_CustomerId. Как видно из запроса, используется поле CustomerId, который является Primary Key. Непонятно, почему Scan, а не Seek?
13 мар 17, 22:19    [20291521]     Ответить | Цитировать Сообщить модератору
 Re: Index Scan в плане  [new]
ZeroFrost
Member

Откуда:
Сообщений: 5
Поправочка - который является "Clustered Key", а не "Primary Key".
13 мар 17, 22:22    [20291533]     Ответить | Цитировать Сообщить модератору
 Re: Index Scan в плане  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31783
ZeroFrost
Меня интересует Index Scan IX_Order_CustomerId. Как видно из запроса, используется поле CustomerId, который является Primary Key. Непонятно, почему Scan, а не Seek?
Что конкретно нужно найти в таблице Order операцией Seek, строку с каким значением CustomerId?

Для выполнения этого запроса существует 2 пути (логических):

1 - взять все записи из таблицы Customer, для каждой найти запись в таблице Order операцией Seek в Scan IX_Order_CustomerId, потом лукапом найти запись операцией Seek по кластерному индексу PK_Order

2 - взять все записи из таблицы Order, для каждой найти запись в таблице Customer операцией Seek по кластерному индексу PK_Customer.

Очевидно, что второй вариант намного быстрее, и по первому пути сиквел никогда не пойдёт.
13 мар 17, 22:46    [20291620]     Ответить | Цитировать Сообщить модератору
 Re: Index Scan в плане  [new]
invm
Member

Откуда: Москва
Сообщений: 9646
Таблица Order находится на внешнем входе Nested Loops и считывается целиком. Поэтому Scan кластерного индекса.
13 мар 17, 22:55    [20291637]     Ответить | Цитировать Сообщить модератору
 Re: Index Scan в плане  [new]
ZeroFrost
Member

Откуда:
Сообщений: 5
alexeyvg, invm
Спасибо за ответы! Я немного запутался и пропустил самую важную вещь - берутся ВСЕ записи (поэтому и Scan). Если добавить фильтр (where c.CustomerId = 1), то получится то, что нужно - два Seek'a.
@alexeyvg
В Вашем ответе небольшая неточность (выделил жирным). Первичный ключ (PK_Order) в таблице Order - НЕкластерный, а кластерный индекс - IX_Order_CustomerId
alexeyvg
Для выполнения этого запроса существует 2 пути (логических):

1 - взять все записи из таблицы Customer, для каждой найти запись в таблице Order операцией Seek в Scan IX_Order_CustomerId, потом лукапом найти запись операцией Seek по кластерному индексу PK_Order

2 - взять все записи из таблицы Order, для каждой найти запись в таблице Customer операцией Seek по кластерному индексу PK_Customer.

Очевидно, что второй вариант намного быстрее, и по первому пути сиквел никогда не пойдёт.


Откуда в первом варианте Lookup, когда IX_Order_CustomerId - кластерный?
13 мар 17, 23:19    [20291695]     Ответить | Цитировать Сообщить модератору
 Re: Index Scan в плане  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 31783
ZeroFrost
В Вашем ответе небольшая неточность (выделил жирным). Первичный ключ (PK_Order) в таблице Order - НЕкластерный, а кластерный индекс - IX_Order_CustomerId
Да, точно, не заметил.
Тогда, получается, эти 2 варианта равнозначны.
Можно сканировать Customer, а потом взять записи, используя Seek по IX_Order_CustomerId

ZeroFrost
Если добавить фильтр (where c.CustomerId = 1), то получится то, что нужно - два Seek'a.
Ну да, с фильтром будет 2 Seek-а
14 мар 17, 09:24    [20292144]     Ответить | Цитировать Сообщить модератору
 Re: Index Scan в плане  [new]
ZeroFrost
Member

Откуда:
Сообщений: 5
Всем спасибо за ответы
14 мар 17, 20:19    [20295122]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить