Селективность CustomerID
сыграет определенную роль в решении оптимизатора запросов. Если, с одной стороны, он был уникальным, то операция равенства даст не более одного результата, поэтому операция SEEK / LOOKUP почти гарантирована. Если, с другой стороны, потенциально сотни или тысячи записей будут соответствовать значению CustomerID, сканирование кластерного индекса может показаться более привлекательным.
Вы будете удивлены, насколько избирательным должен быть фильтр, чтобы исключить сканирование. Я не могу найти статью, из которой первоначально извлек эту цифру, но если CustomerID 1234 будет соответствовать всего 4% записей в таблице, сканирование кластерного индекса может быть более эффективным или, по крайней мере, выглядеть так оптимизатор (который не делает это правильно 100% времени).
Звучит, по крайней мере, правдоподобно, что статистика, хранящаяся в некластеризованном индексе CustomerID, заставляет оптимизатор переключаться между поиском и сканированием на основе критериев селективности.
Возможно, вы сможете уговорить оптимизатор к использованию индекса, введя операцию JOIN или EXISTS:
-- Be aware: this approach is untested
select o.*
from Orders o
inner join Customers c on o.CustomerID = c.CustomerID
where c.CustomerID = 1234;
Или:
-- Be aware: this approach is untested
select o.*
from Orders o
where exists (select 1
from Customers c
where c.CustomerID = 1234 and
o.CustomerID = c.CustomerID);
Также имейте в виду, что при таком подходе EXISTS
, если у вас нет индекса для предиката «соединения» (в данном случае, поля CustomerID) в обеих таблицах, тогда вы закончите с вложенным циклом, который мучительно медленный. Использование внутренних объединений кажется гораздо безопаснее, но время от времени подход EXISTS
имеет свое место, когда он может использовать индексы.
Это всего лишь предложения; Я не могу сказать, будут ли они эффективными или нет. Просто что-то попробовать, или для постоянного эксперта, чтобы подтвердить или опровергнуть.