Левое соединение не оптимизировано

В базе данных SQL Server рассмотрим классическое родительско-дочернее отношение, подобное следующему:

create table Parent(
p_id uniqueidentifier primary key,
p_col1 int,
p_col2 int
);

create table Child(
c_id uniqueidentifier primary key,
c_p uniqueidentifier foreign key references Parent(p_id)
);

declare @Id int
set @Id = 1
while @Id <= 10000
begin
insert into Parent(p_id, p_col1, p_col2) values (NEWID(), @Id, @Id);
set @Id=@Id+1;
end
insert into Child(c_id, c_p) select NEWID(), p_id from Parent;
insert into Child(c_id, c_p) select NEWID(), p_id from Parent;
insert into Child(c_id, c_p) select NEWID(), p_id from Parent;
;

Теперь у меня есть эти два эквивалентных запроса, один из которых использует inner, а другой использует left join:

Внутренний запрос:

select *
from Child c
inner join Parent p
on p.p_id=c.c_p
where p.p_col1=1 or p.p_col2=2;

Левый запрос на присоединение:

select *
from Child c
left join Parent p
on p.p_id=c.c_p
where p.p_col1=1 or p.p_col2=2;

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

План для запроса левого соединения таков:

Оптимизатор работает хорошо, выбирая тот же план, если у меня есть только одно условие, например:

where p.p_col1=1 

Но если я добавлю "или" во второй другой столбец, он больше не выберет лучший план:

where p.p_col1=1 or p.p_col2=2;

Я что-то упустил или это просто оптимизатор упускает это улучшение?

2 ответа

Решение

Понятно, что это оптимизатор.

Когда у вас есть одно условие в WHERE условие (и "условие" может быть условием, связанным с ANDс, но не ORs), тогда оптимизатор может легко достичь пика и сказать "да, условие имеет строки из второй таблицы, нет NULL Сравнение значений, так что это действительно внутреннее соединение ".

Эта логика становится сложнее, когда условия связаны OR, Я думаю, вы заметили, что оптимизатор не делает этого для более сложных условий.

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

Другие вопросы по тегам