Há uns dias coloquei aqui um post sobre eliminação de joins e, sem querer, deparei-me hoje com uma situação onde parecia que o SQL Server não estava a fazer um bom trabalho.
Vai-se a ver… e quem não estava a fazer um bom trabalho éramos nós.
A situação era bem mais complicada do que esta, mas se pegarmos no código do último post é rápida de explicar.
Vamos lá de novo.
create table JoinEliminationDemo01
(
id int identity primary key
, Col1 uniqueidentifier
)
go
insert into JoinEliminationDemo01
(Col1)
select NEWID()
go 10
create table JoinEliminationDemo02
(
id int identity primary key
, id_ref int not null
, Col1 uniqueidentifier
)
go
insert into JoinEliminationDemo02
(id_ref, Col1)
select (ABS(CHECKSUM(NEWID()))%10)+1, NEWID()
from sys.objects a
cross join sys.objects b
go
ALTER TABLE JoinEliminationDemo02
ADD CONSTRAINT
JoinEliminationDemo02__id_ref__id FOREIGN KEY(id_ref)
REFERENCES JoinEliminationDemo01 (id)
Imaginemos que neste caso queremos a Col1 da JoinEliminationDemo02 e do id da JoinEliminationDemo01.
É muito simples fazer este erro em queries mais complexas com uma mão-cheia de joins.
set statistics time, io on
select a.Col1
, b.id
from JoinEliminationDemo02 a
inner join JoinEliminationDemo01 b
on b.id = a.id_ref


Neste exemplo simples percebemos que a nossa execução está a tocar nas duas tabelas quando temos criada uma relação para evitar isso mesmo.
Facilmente chegamos à solução.
Estamos a retirar valores de uma e de outra tabela e, nestes casos, o SQL Server não consegue eliminar a referência.
Se formos buscar o valor que precisamos à JoinEliminationDemo02 o join deverá ser eliminado.
select a.Col1
, a.id_ref
from JoinEliminationDemo02 a
inner join JoinEliminationDemo01 b
on b.id = a.id_ref


Parece óbvio, mas nem sempre é.