Desafio: Cadê meu Join?
Dessa vez apresento um desafio curioso que recebi esses dias enquanto estava no escritório. Uma pessoa me apresentou uma consulta SQL que relacionava os dados de cliente com os endereços.
SELECT
c.*FROM Clientes c LEFT OUTERJOIN Regioes r
ON c.regiaoId = r.regiaoId AND
r.regiaoId ISNULL
O interessante é que o plano de execução gerada não possui JOIN entre tabelas. Surge a pergunta: CADÊ MEU JOIN???
O problema fica mais interessante quando substituimos o LEFT OUTER JOIN por um INNER JOIN, pois o plano de execução não apresenta a leitura em nenhuma tabela.
SELECT
c.*FROM Clientes c INNERJOIN Regioes r
ON c.regiaoId = r.regiaoId AND
r.regiaoId ISNULL
A pergunta desse Desafio Ninja é:
O que aconteceu com o Join de tabela e com a operação de Table Scan?
Poste sua opinião e resposta na seção de comentários.
Script usado:
CREATE TABLE Regioes (regiaoId INT PRIMARY KEY, local VARCHAR(100) NOT NULL)CREATE TABLE Clientes (id INT, nome VARCHAR(50), regiaoId INT FOREIGN KEY REFERENCES Regioes(regiaoId)) INSERT Regioes VALUES (1, 'Norte'), (2, 'Sul')INSERT Clientes VALUES (1, 'Cliente1', 1), (2, 'Cliente2', 1)GO SELECT c.* FROM Clientes c LEFT JOIN Regioes r ON c.regiaoId = r.regiaoId AND r.regiaoId IS NULL SELECT c.* FROM Clientes c INNER JOIN Regioes r ON c.regiaoId = r.regiaoId AND r.regiaoId IS NULL |
Comments
Anonymous
January 24, 2012
Essa eu vi no PASS 2011 :) O SQL é esperto o suficiente para saber que já que eu defini que RegiaoID não pode ser NULO, então quando faço uma busca que foge uma FK ou uma check constraint (no caso "WHERE regiaoId IS NULL") o otimizador nem precisa ir na tabela para ter certeza que não vai retornar nenhuma linha ÓTIMO DESAFIO heehheehheAnonymous
January 24, 2012
É isso ai!!! Matou fácil fácil.. :)Anonymous
February 09, 2012
Legal o desafio. Compartilho da resposta do Sérgio. Semana passada passei por um problema semelhante analisando um plano de execução e não sabia do que se tratava. Fui procurar quem "manja" do QO e falei com o Fabiano Amorim, e ele me passou o link de um artigo que ele escreveu exatamente sobre isto. O link é este: www.simple-talk.com/.../query-optimizer-and-cartesian-products Bacana! Abraços, Erickson RicciAnonymous
February 12, 2012
O desafio é bastante curioso e exemplifica parte do funcionamento inteligente do Query Optimizer (QO).Anonymous
May 21, 2012
Grande Catae, este caso poderia ser considerado um contradiction na fase simplification ?Anonymous
May 23, 2012
Exato! Você está 100% correto.Anonymous
May 23, 2012
Obrigado pela conversa Laerte. Deixo explicar a quem eventualmente estiver lendo esse comentário: Laerte me fez a pergunta no blog e por MSN sobre o que seria "contradiction na fase de simplification". Na hora, respondi que não conhecia exatamente o termo de contradiction. Ele me passou algumas referencias para estudar e agora sei o que é isso. Valeu Laerte.Anonymous
July 19, 2012
The comment has been removedAnonymous
July 25, 2012
Com certeza, essa frase resume o comportamento do SQL Server: Não acredito que o SQL seja "esperto", mas sim que seja "prático", pois ele planeja a execução realizando a leitura das páginas de dados que serão utilizadas e apresenta o plano de execução executado para as tais leituras.Anonymous
March 14, 2013
Muito interessante, não sabia dessa do otimizador...Anonymous
April 09, 2013
E no caso do LEFT JOIN, como nenhuma coluna da tabela à direita foi usada, então o SQL não precisa fazer nenhuma leitura lá pois o resultado não vai impactar já que de qualquer maneira todas as linhas da tabela da esquerda serão retornadas. Agora o interessande disso é perceber tambem como o processaento lógico da query funciona... Se você colocar o filtro "r.regiaoId IS NULL" na cláusula WHERE em vez da cláusula ON, as coisas mudam um pouquinho ... :) Acho que esse é bom exemplo pros desenvolvedores entenderem quando ON e WHERE podem trazer resultados diferentes.Anonymous
April 16, 2013
É verdade, há uma diferença bem grande entre esses tipos de JOIN entre tabelas.