Desafio: Cadê meu Join?

Desafio: Cadê meu Join?

  • Comments 12

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 OUTER JOIN Regioes r
ON c.regiaoId = r.regiaoId AND
r.regiaoId IS NULL

O interessante é que o plano de execução gerada não possui JOIN entre tabelas. Surge a pergunta: CADÊ MEU JOIN???

image

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 INNER JOIN Regioes r
ON c.regiaoId = r.regiaoId AND
r.regiaoId IS NULL

image

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

  • 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 heehheehhe

  • É isso ai!!! Matou fácil fácil.. :)

  • 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 Ricci

  • O desafio é bastante curioso e exemplifica parte do funcionamento inteligente do Query Optimizer (QO).

  • Grande Catae, este caso poderia ser considerado um contradiction na fase simplification ?

  • Exato! Você está 100% correto.

  • 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.

  • Estou procurando o desafio rs...

    Para a construção do Perform Plan é necessário validar as relações e as páginas de dados que serão consultadas, de outra forma não é possível ter um plano de execução.

    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.

    Hora, se o registro nulo não retornou dado algum para a leitura, então nenhum plano de execução foi construído e é isso que vemos impresso pelo SQL.

    Parabéns pelo desafio! Não é trivial e é muito interessante!

  • 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.

  • Muito interessante, não sabia dessa do otimizador...

  • 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.

  • É verdade, há uma diferença bem grande entre esses tipos de JOIN entre tabelas.

Page 1 of 1 (12 items)
Leave a Comment
  • Please add 2 and 5 and type the answer here:
  • Post