30/09/2004

Inner Join ou Where - Qual o quot;melhorquot;?

Bom dia a todos.

Essa é uma dúvida que sempre me acompanhou. Sei das vantagens de se utilizar o Join no caso do left ou right e full. Porém no caso o Inner Join e do Where exite alguma diferença de performance em utilizar um outro tipo de relacionamento de tabela? Minha dúvida surgiu quando notei que o Código SQL Gerado pelo Access em suas consultas usa Join enquanto o código SQL Gerado pelo MsQuery utiliza Where, com isso deduzi que não há diferença de perfomance, mas gostaria da opinião dos colegas quanto a isso.

Abraço a todos.

Oberdan. :!:


Oberdan

Respostas

30/09/2004

Afarias

INNER JOIN é uma sintaxe mais moderna. É melhor por 2 pontos::

1- mais organizada e fácil de ler (para o desenvolvedor)
2- melhor para os otimizadores (dos bancos) achar o melhor plano de ação para a realização da consulta

Em geral não deve haver diferenças de performance entre as duas, mas contando com o ponto 2 citado acima, numa consulta mais complexa um ´otimizador´ poderia achar um plano melhor para o inner q para o where (mas isso não é para ocorrer)



T+


Responder Citar

30/09/2004

Tnaires

Eu convivi com uma melhoria prática usando JOINs em lugar d WHEREs. Uma vez, eu queria alterar um registro q uma consuita q eu fiz retornou (ela só tinha WHEREs). Na hora d gravar, dava erro, mas qdo eu substituí por JOINs, ele deixou eu alterar o registro.


Responder Citar

30/09/2004

Isaiasbass

Só aproveitando o tópico

Estou tendo um baita problema com performance na hora de pesquisa para relatórios.

Uso InterBase 6.0
São Joins onde só uso wheres e agora q fiz uma importação de uma base de mais de 100MB q tem tablas de cerca de 600 mil registros então os relatorios ficaram super lentos para exibição.

Queria um exmplo básico do Inner Join relacionando 3 ou mais tabelas para q eu posa fzer testes de performance.

Obrigado.


Responder Citar

30/09/2004

Afarias

select {lista de campos} from tabela1 t1
inner join tabela2 t2 on (t1.campo_chave=t2.campo_chave)
inner join tabela3 t3 on (t2.campo_chave=t3.campo_chave)
{...}
where
{...}



por exemplo, selecionar todos os ítens (serviços) de ordens de serviço emitidas em determinada data, contendo número e data da ordem, nome do solicitante, informações do serviço -- segue o metadata (simplificado)

[solicitantes]
codigo
nome

[servicos]
codigo
descricao

[ordens]
numero
data
cod_solicitante

[itens]
num_ordem
cod_servico


select sol.nome, ser.descricao, ord.numero, ord.data 
  from ordens ord
  inner join solicitantes sol on (sol.codigo=ord.cod_solicitante)
  inner join itens ite on (ite.num_ordem=ord.numero)
  inner join servicos ser on (ser.codigo=ite.cod_servico)
where
 ord.data = :alguma_data




T+


Responder Citar

01/10/2004

Aguiarle

select {lista de campos} from tabela1 t1
inner join tabela2 t2 on (t1.campo_chave=t2.campo_chave)
inner join tabela3 t3 on (t2.campo_chave=t3.campo_chave)
{...}
where
{...}
por exemplo, selecionar todos os ítens (serviços) de ordens de serviço emitidas em determinada data, contendo número e data da ordem, nome do solicitante, informações do serviço -- segue o metadata (simplificado) [solicitantes] codigo nome [servicos] codigo descricao [ordens] numero data cod_solicitante [itens] num_ordem cod_servico
select sol.nome, ser.descricao, ord.numero, ord.data 
  from ordens ord
  inner join solicitantes sol on (sol.codigo=ord.cod_solicitante)
  inner join itens ite on (ite.num_ordem=ord.numero)
  inner join servicos ser on (ser.codigo=ite.cod_servico)
where
 ord.data = :alguma_data
T+




ao inves de usar o where, faco o filtro na propria juncao

select sol.nome, ser.descricao, ord.numero, ord.data 
  from ordens ord
  inner join solicitantes sol on (sol.codigo=ord.cod_solicitante)
  inner join itens ite on (ite.num_ordem=ord.numero)
  inner join servicos ser on (ser.codigo=ite.cod_servico) and

 (ord.data = :alguma_data)



Responder Citar

01/10/2004

Afarias

|ao inves de usar o where, faco o filtro na propria juncao

Mas está errado. No mínimo conceitualmente errado.

A sintaxe do INNER JOIN procura justamente separar RELACAO de ´FILTRO´ (era tudo junto no WHERE) -- e vc pega e junta tudo no JOIN??


T+


Responder Citar

01/10/2004

Paulo_amorim

Olá

Só lembrando, essa sintaxe com JOIN não funciona em ORACLE antes da versão 9i , na qual ela foi implementada.

Nessas versões anteriores, a sintaxe de INNER JOIN deve ser feita no WHERE, bem como a de OUTER JOIN, que deve ser feita colocando ´(+)´ no campo de menor importância

Até+


Responder Citar

01/10/2004

Afarias

É verdade, o Oracle só implementou a sintaxe ANSI-92 de joins recentemente.


T+


Responder Citar

01/10/2004

Aguiarle

|ao inves de usar o where, faco o filtro na propria juncao Mas está errado. No mínimo conceitualmente errado. A sintaxe do INNER JOIN procura justamente separar RELACAO de ´FILTRO´ (era tudo junto no WHERE) -- e vc pega e junta tudo no JOIN?? T+


Nos testes q eu fiz o redimento do filtro na juncao das tabelas e consideravelmente notavel, pois ele monta a tabela filtrando o nao desejado. Ja com o where ele monta a tabela com todas as possibilidades de acordo com o join e depois faz esta filtragem do where. Pelo menos com no banco interbase eu notei isto.


Responder Citar

01/10/2004

Afarias

|Nos testes q eu fiz o redimento do filtro na juncao das tabelas e
|consideravelmente notavel,

Que versão do IB? Pode postar aqui um teste pático onde notou essa diferença??

Fiquei curioso pq eu nunca vi um plano de execução do IB 6.0 ou no FB 1.0 que se mostrase diferente entre as duas formas.


|Ja com o where ele monta a tabela com todas as possibilidades de
|acordo com o join e depois faz esta filtragem do where.

Não... depende do JOIN, tabelas envolvidas e tals... mas geralmente o WHERE é ´executado´ antes.

Um exemplo simples é::

select nota.data, item.produto, item.qtde
from nota inner join item on (item.nota = nota.numero)
where nota.vendedor = x

num banco contendo 1000 notas e apenas 10 do vendedor x, apenas 10 registros da tabela nota seriam lidos (10 reads em nota).



T+


Responder Citar

01/10/2004

Aguiarle

|Nos testes q eu fiz o redimento do filtro na juncao das tabelas e |consideravelmente notavel, Que versão do IB? Pode postar aqui um teste pático onde notou essa diferença?? Fiquei curioso pq eu nunca vi um plano de execução do IB 6.0 ou no FB 1.0 que se mostrase diferente entre as duas formas. |Ja com o where ele monta a tabela com todas as possibilidades de |acordo com o join e depois faz esta filtragem do where. Não... depende do JOIN, tabelas envolvidas e tals... mas geralmente o WHERE é ´executado´ antes. Um exemplo simples é:: select nota.data, item.produto, item.qtde from nota inner join item on (item.nota = nota.numero) where nota.vendedor = x num banco contendo 1000 notas e apenas 10 do vendedor x, apenas 10 registros da tabela nota seriam lidos (10 reads em nota). T+


faca um teste com tabelas q vc possua q contenham muitos registros e marque o tempo gasto nos dois casos.

no meu caso, eu tenho uma tabela de pedidos com registros consideraves que busca informacoes em outras duas tabelas menores,

quando eu tirei o where e coloquei o filtro no inner join ela me retornou um resultado melhor.

Ex:

select nota.data, item.produto, item.qtde
from nota inner join item on (item.nota = nota.numero) and (
nota.vendedor = x)


Responder Citar

01/10/2004

Afarias

|faca um teste com tabelas q vc possua q contenham muitos registros e
|marque o tempo gasto nos dois casos.

Já fiz isso. obtive os mesmos resultados.


|no meu caso, eu tenho uma tabela de pedidos com registros
|consideraves que busca informacoes em outras duas tabelas menores,

pode postar aqui o SQL (SELECT) para q eu possa constatar??
aproveita e me passa qual a versão do IB onde viu isso ocorrer.


|quando eu tirei o where e coloquei o filtro no inner join ela me retornou
|um resultado melhor.

Pois me passe esse SQL pq todos q testei não apresentaram isto (pode deixar q as tabelas eu ´simulo´ aqui)



T+


Responder Citar

01/10/2004

Vinicius2k

Colegas,

Acho que deve ser analisado também o lado dos índices...

Se o Tabela A tiver um índice de pior seletividade que a Tabela B, ou mesmo não contiver um índice para o campo do WHERE, caso a B tenha um índice bom, consequentemente o ´filtro´ aplicado sobre ela (B) terá performance superior... Estou errado?

Se, em teoria, as instruções deveriam responder com a mesma performance, a única possível explicação que vejo é esta.
Só verificando a analise do PLAN para comprovar essa suposição...

T+


Responder Citar

01/10/2004

Afarias

|Acho que deve ser analisado também o lado dos índices...

Contando q estejamos tratando do mesmo campo (´filtro´), mudando apenas sua ´colocação´ dentro do SELECT, acho q a seletividade do índice não fará diferença -- admitindo q os índices necessários existam.


|Só verificando a analise do PLAN para comprovar essa suposição...

Por isso gostaria de ter o SQL, pq o normal (que tenho visto) é obter o mesmo plan para qualquer das situações.



T+


Responder Citar

01/10/2004

Kenshindigital

se ele executou a mesma query primeiro após conectar o banco pela primeira vez usando where a query pode ter demorado porque não havia cache, a primeira query usando determinada tabela geralmente demora mais.
Tente testar novamente depois de o banco ter cacheado a tabela.


Responder Citar