Array
(
)

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

Oberdan
   - 30 set 2004

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. :!:


Afarias
   - 30 set 2004

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+


Tnaires
   - 30 set 2004

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.


Isaiasbass
   - 30 set 2004

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.


Afarias
   - 30 set 2004

#Código


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


#Código

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+


Aguiarle
   - 01 out 2004


Citação:
#Código


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


#Código

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

#Código

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)



Afarias
   - 01 out 2004

|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+


Paulo_amorim
   - 01 out 2004

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é+


Afarias
   - 01 out 2004

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


T+


Aguiarle
   - 01 out 2004


Citação:
|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.


Afarias
   - 01 out 2004

|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+


Aguiarle
   - 01 out 2004


Citação:
|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)


Afarias
   - 01 out 2004

|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+


Vinicius2k
   - 01 out 2004

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+


Afarias
   - 01 out 2004

|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+


Kenshindigital
   - 01 out 2004

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.