Левое соединение не оптимизировано - PullRequest
0 голосов
/ 07 декабря 2018

В базе данных 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;
;

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

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

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 будет достаточно умен, чтобы выяснить один и тот же план выполнения для этих двух запросов,но это не тот случай.План для внутреннего запроса таков: enter image description here

План для запроса левого соединения такой: enter image description here

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

where p.p_col1=1 

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

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

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

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

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

0 голосов
/ 07 декабря 2018

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

Если в предложении WHERE имеется одно условие (и условие может быть условием, связанным с AND с, но не OR с)затем оптимизатор может легко определить и сказать «да, условие имеет строки из второй таблицы, нет сравнения значений NULL, так что это действительно внутреннее объединение».

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

...