Jump to content

Archived

This topic is now archived and is closed to further replies.

Chrnos

Performance de consulta

Recommended Posts

Tenho uma dúvida, espero que os colegas possam me ajudar....

 

Por hábito, sempre monto meus sqls usando o Inner/Left Join passando as chaves que ligam as tabelas envolvidas nele e algumas vezes alguns outros filtros específicos da tabela usada no join... mas vejo muitos códigos em que o uso do mesmo é inexistente e que a ligação entre as tabelas é feita diretamente no where.... a dúvida é: para o BD, quando se trata de performance de execução, é mais vantajoso usar:

 

 

Select A.CampoX, B.CampoY
from tabelaA A
Inner Join TabelaB B On (b.codigo = a.codigo)

 

ou usar:

 

 

Select A.CampoX, B.CampoY
from tabelaA A, TabelaB B
where b.codigo = a.codigo

 

Alguém pode me sanar esta dúvida, explicando porque uma forma é mais vantajosa que a outra?

Share this post


Link to post
Share on other sites

Que eu saiba dá na mesma, nas versões mais modernas de BD, o otimizador de queries fará a mesma coisa.

 

O mesmo não vale para outer join.

Share this post


Link to post
Share on other sites

Olá Chrnos,

 

Complementando as dicas dos colegas, quando você escreve sua instrução usando o inner/left join, você esta usando o padrão ANSI SQL, quando usa na cláusula where, não esta seguindo este padrão.

 

Já fiz vários testes, em nenhum consegui resultados que garantissem que o modelo a ou b seja melhor.

 

Espero ter lhe sido útil, grande abraço.

 

_ _

Fabiano Abreu

Papo SQL

Share this post


Link to post
Share on other sites

Mas creio que isto dependa do BD e da versão deste, a forma que o Otimizador de queries atua.

Share this post


Link to post
Share on other sites

Obrigado pelas respostas, vou dar uma lida no artigo quando estiver em casa... eu particularmente prefiro usar sempre o inner join/left join, até pra facilitar a leitura do sql... mas sempre tive curiosidade em saber se um dos dois modos era melhor, porque como programador sempre tento deixar minhas rotinas o mais otimizado possível e com a melhor performance possível.

 

 

Grato a todos, se ninguém tiver mais nada a acrescentar a discussão, pode considerar o tópico resolvido.

Share this post


Link to post
Share on other sites

Existe diferença sim!

Façam um teste analisando o plano de execução de cada uma das sintaxes. Existe diferença de leitura de disco, hash de dados entre outros itens.

Estou sem tempo de postar agora e eu tinha um artigo no MSDN sobre o assunto mas não encontrei ainda. Assim que eu acabar umas modelagens de BI e umas cargas de ETL eu volto a postar mais detalhes.

 

Abçs

Share this post


Link to post
Share on other sites

No Sql Server o uso do inner join força a leitura pelo índice da PK ?

 

Na versão do Oracle(11) que tenho aqui o Plano de Execução ficou igual para join explícito e implícito.

 

 

 

 

No Oracle tem uma diretiva HINT que permite indicar um caminho para o Otimizador.

 

 

Detalhe, o Otimizador pode (@6@7 para este hist

 

Algo assim

 

 

select /*+ index_asc(tabela indice) */

from ....

Share this post


Link to post
Share on other sites

no sql tb tem o indicador para o caminho do index. fica dentro do with

select * from table with(index = xxx) por exemplo

por join ele forca pela pk, mas se o where ou o join nao estiver em pk ele vai para algum indice criado

Share this post


Link to post
Share on other sites

Discordo quando se diz que é a mesma coisa .....

 

Estamos em um fórum de SQL Server, então vou me basear no SQL Server .....

 

 

Eu fiz um teste no banco de dados que com duas das maiores tabelas que tenho e plano de execução realmente deu igual

 

OBS: estatísticas estão atualizadas .....

 

Contudo na prática do dia a dia, a forma com inner join é bem mais rápida .....

 

PORQUE ???

 

Na minha humilde opinião pela forma como o SQL em geral é executado .....

 

A cada inner join ele cria uma tabela virtual com os resultados, ou seja, ele vai efetuando a consultado aos poucos digamos assim....

 

Se você usa junção simples

 

select '' from 
tabela1, tabela2, tabela3
where tabela1.cod1 = tabela2.cod1 and tabela2.cod2 =  tabela2.cod2

 

Ele fará permutação de de todos os registros e só no fim fará o filtro de tudo, ou seja, se cada tabela tiver 100 registros ele criará uma tabela virtual com 1000000 de registros para depois efetuar a filtragem que pode trazer 200 registros

 

Usando

 

select '' from 
tabela1 inner join tabela2
        on tabela1.cod1 = tabela2.cod1
inner join tabela3
        on tabela3.cod2 = tabela2.cod2

 

O código é executado em 2 etapas ele permuta tabela1 e tabela2 o que dá 10000 registros e filtra os resultados desejados, digamos

100 registros que são armazenados em uma tabela virtual em memoria e essa tabela de 100 registros que será permutada e filtrada com tabela3, o que dá 20000 registros 30000 no total das duas operações e não 1000000 como na primeira simulação..

 

Essa é minha opinião mas o melhor professor é o dia a dia

 

Espero ter dado minha contribuição na conversa

 

Essa questão de tabela virtual eu li nesse livro

 

http://www.amazon.com/Inside-Microsoft%C2%AE-SQL-Server%C2%AE-2008-ebook/dp/B0043EWUUW/ref=sr_1_1?ie=UTF8&qid=1384903148&sr=8-1&keywords=Microsoft+Press+-+Inside+Microsoft+Server+2008+T-SQL+Querying

Share this post


Link to post
Share on other sites

Discussão legal, é para isto que o fórum existe.

 

No Oracle uma segunda consulta nos mesmos dados seria em tese mais rápida pois os dados estariam na memória.

 

Creio que uma solução medir várias queries, diversas vezes e com diferentes parametros e medir uma média.

 

Alguém já deve ter feito este PTC, vou dar uma pesquisada nisto qualquer hora.

Share this post


Link to post
Share on other sites

Acho que se monitorar pela DMV de memoria e disco pode-se chegar a algum resultado concreto.

Eu tinha feito este estudo já para definição de regras de negócio, nomenclaturas de objetos, etc...

 

Vou pedir para a consultoria me mandar e eu posto aqui o resultado....

Share this post


Link to post
Share on other sites
Vou voltar a este post, pois não consegui a documentação que eu fiz. Porém estou lendo um livro "Microsoft®
SQL Server® 2008 Bible" e cheguei justamente neste ponto colocado pelo @Chrnos.
De acordo com o livro na página 234:

 

ANSI SQL 89 joins
A join is really nothing more than the act of selecting data from two tables for which a condition of
equality exists between common columns. Join conditions in the ON clause are similar to WHERE clauses.
In fact, before ANSI SQL 92 standardized the JOIN...ON syntax, ANSI SQL 89 joins (also called legacy
style joins, old style joins, or even grandpa joins) accomplished the same task by listing the tables within
the FROM clause and specifying the join condition in the WHERE clause.
The previous sample join between Contact and [Order] could be written as an ANSI 89 join as follows:

 

 

[sql]
SELECT Contact.ContactCode, [Order].OrderNumber
FROM dbo.Contact, dbo.[Order]
WHERE [Order].ContactID = Contact.ContactID
ORDER BY ContactCode;
[/sql]

 


 

Best Practice
Always code joins using the ANSI 92 style. ANSI 92 joins are cleaner, easier to read, and easier to debug
than ANSI 89 style joins, which leads to improved data integrity and decreases maintenance costs. With
ANSI 89 style joins it’s possible to get the wrong result unless it’s coded very carefully. ANSI 89 style outer
joins are deprecated in SQL Server 2008, so any ANSI 89 outer joins will generate an error.

 

Ou seja, ambos tem o mesmo comportamento se olharmos para padrão ANSI que é utlizado no SQLServer e por boas práticas, devemos utilizar JOIN e não na cláusula WHERE.
Ok, concordo que o comportamento é o mesmo, mas em um lab que montei, notei que temos uma diferença na leitura de um ponteiro de disco.
Analisando pelo Windows Perform as estatisticas de disco, temos um aumento de aproximademente 1% chegando a 3% de aumento de I/O. Pode ser insignificante em algumas aplicações, porém, no meu caso, 3% já um nível a ser considerado.
Para este teste utilizei o SQL QueryStress em DUAS tabelaS de 1 milhão de registros cada e com 5 colunas entre elas.
Uma consulta simples retornando as 10 colunas, com dois campos de indices criados conforme analise do plano de execução e da analise do SQL Sentry Plan Explorer
Pelas DMV´s não cheguei nem a testar, pois se pelo Perform já foi possível checar.
Enfim, é isso.

Share this post


Link to post
Share on other sites

×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.