[Oracle] A ordem dos WHEREs altera a busca?

11 respostas
Rafael_Afonso

Olá:

Suponham as seguintes queries dentro do Oracle:
Query 1:

SELECT * FROM pessoa, casa  
WHERE pessoa.nome like 'A%' AND casa.codigo = pessoa.endereco AND casa.estado = 'SP'

Query 2:

SELECT * FROM pessoa, casa 
WHERE casa.estado = 'SP' AND pessoa.endereco = casa.codigo AND pessoa.nome like 'A%'

:?: A ordem das clausulas where afetará a forma como a busca é feita (acho que sim)? Ou seja: na Query 1 buscar-se-á primeiro por nome de pessoa e depois por estado de casa e na Query 2 buscar-se-á primeiro por estado de casa e depois por nome de pessoa (também acho que sim)? Se tivermos 200.000 pessoas e 2.000 casas, então a query 1 será mais lenta que a query 2? Ou o Oracle fará alguma otimização?

Grato,

11 Respostas

Daniel_Quirino_Olive

“Rafael Afonso”:
Olá:

Suponham as seguintes queries dentro do Oracle:
Query 1:

SELECT * FROM pessoa, casa  
WHERE pessoa.nome like 'A%' AND casa.codigo = pessoa.endereco AND casa.estado = 'SP'

Query 2:

SELECT * FROM pessoa, casa 
WHERE casa.estado = 'SP' AND pessoa.endereco = casa.codigo AND pessoa.nome like 'A%'

:?: A ordem das clausulas where afetará a forma como a busca é feita (acho que sim)? Ou seja: na Query 1 buscar-se-á primeiro por nome de pessoa e depois por estado de casa e na Query 2 buscar-se-á primeiro por estado de casa e depois por nome de pessoa (também acho que sim)? Se tivermos 200.000 pessoas e 2.000 casas, então a query 1 será mais lenta que a query 2? Ou o Oracle fará alguma otimização?

Grato,

As duas queries são diferentes, apesar de produzirem resultados iguais.
Mas a maioria dos RDBMSs fazem otimizações, como, por exemplo, remover a condição casa.codigo = pessoa.endereco da sua cláusula WHERE, transformando-a em um Inner Join (… casa c inner join pessoa p on c.codigo = p.endereco …).

[editado]
Opa, o Oracle não possui “Inner Join” :roll: .
Bom, o que seu banco de dados faz ao executar a primeira query

SELECT * FROM pessoa, casa WHERE pessoa.nome like 'A%' AND casa.codigo = pessoa.endereco AND casa.estado = 'SP'

é filtrar as pessoas cujo nome comece com a letra “A” e fazer um produto cartesiano com a tabela “CASA”, segundo a condição de junção.

Já a segunda query

SELECT * FROM pessoa, casa
WHERE casa.estado = 'SP' AND pessoa.endereco = casa.codigo AND pessoa.nome like 'A%'

filtra as casas que ficam no estado de São Paulo e faz um produto cartesiano com a tabela “PESSOA”.
A mais rápida será aquela que conseguir fazer o produtor cartesiano mais rápido, ou seja, aquela que retornar menos tuplas no primeiro filtro.
[/editado]

danieldestro

Com certeza existe diferença sim! Principalmente se existe índice (ou não) nos campos e número de registros e tal.

Você pode usar o explanation do Oracle para ele te falar em que ponto está pegando. Usando o Toad você faz isso sem precisar saber os comandos Oracle.

O Oracle faz esses ajustes usando uma package opcional do Oracle, chamada de Oracle Tuning, que custa alguns milhares.

Abraços

Rafael_Steil

Outra coisa eh a forma como voce escreve as queries… o ideal eh vc usar algum padrao sempre… por exemplo,

SELECT x FROM tabela

eh difernte de

select x from tabela

Aqui, “diferente” significa que a comparacao binaria sera diferente, e o oracle ( mysql tmb, e mto provavelmente os outros sistemas ) ira considerar como sendo uma query diferente. Se voce mandar duas queries exatamente iguais ( tudo igual ), o RDBMS pode puxar ela de algum cache, ao inves de fazer o parseamento da query novamente.

Rafael

TedLoprao

Outra coisa, a ordem do where vai depender do método de análise do banco… Se for por Regra ou Custo, por Regra faz diferença… Já por Custo será indiferente a ordem…

Rafael_Afonso

:? Regra? Custo? Como assim? Qual é a definição destes termos?

Grato,

TedLoprao

No Oracle vc pode configurar o otimizador da seguinte maneira:

ALTER SESSION SET OPTIMIZER_MODE = {CHOOSE|RULE|FIRST_ROWS|ALL_ROWS}

O CHOOSE faz com que o bd use Custo se estatísticas estiverem disponíveis e Regra quando não!!!
Regra baseia-se em sintaxe, já o de custo baseia-se em número de leituras lógicas, utilização de CPU e transmissões de rede… Entretanto nesse caso vc precisa ter estatísticas do banco!!!

Diz a lenda que a por regra só existe por compatibilidade!!! Mas não sei se é verdade!!!

Fallow

Claire

Surgiu uma dúvida

Como o Daniel disse, o Oracle não tem Inner Join…
Me disseram que o Inner Join no Oracle é automático. Sem nem precisar de cláusula de comparação…
Isso é verdade???

Bjus
Claire

Daniel_Quirino_Olive

“Claire”:
Surgiu uma dúvida

Como o Daniel disse, o Oracle não tem Inner Join…
Me disseram que o Inner Join no Oracle é automático. Sem nem precisar de cláusula de comparação…
Isso é verdade???

Bjus
Claire


No Oracle há algo que eles chamam de Equi-Join, que é simplesmente fazer a junção na condição da consulta. Mais ou menos assim:

//com Inner Join
select * from Tab1 t1 inner join Tab2 t2 on t1.fkT2 = t2.pk where t1.pk = 1

// a mesma consulta para o Oracle é...
select * from Tab1 t1, Tab2 t2 where t1.fkT2 = t2.pk and t1.pk = 1

Segundo dizem, a primeira consulta normalmente executa mais rápido do que a primeira, pois o produto cartesiano (inner join) é realizado após a seleção de dados (t1.pk = 1), tendo assim uma quantidade de tuplas muito menor para se fazer a junção.

Poxa, será que não tem um DBA aqui? É até risível ouvir uma explicação sobre banco de dados feita por mim. :lol:

Claire

Brigadim Daniel…

Eu prefiro mesmo usar joins… Não sabia fazer no Oracle.

Bjus
Claire

bush

No Oracle existe inner join.

Daniel_Quirino_Olive

É, andei olhando por aí e vi que colocaram Inner Join no 9i. Mas no 8i não tinha :smiley: .

Criado 21 de novembro de 2003
Ultima resposta 21 de nov. de 2003
Respostas 11
Participantes 7