[firebase-br] RES: Consulta demorando 2 horas como resolvo.
Felix
felix.sol em terra.com.br
Seg Jun 6 08:21:25 -03 2011
Luciano,
Testa e reporta o resultado da query do Eduardo?
Fco. Felix
Desenvolvimento de Sistemas
www.soltecnologia.com.br
-----Mensagem original-----
De: lista-bounces em firebase.com.br [mailto:lista-bounces em firebase.com.br] Em
nome de Jáber Lima
Enviada em: segunda-feira, 6 de junho de 2011 08:10
Para: FireBase
Assunto: Re: [firebase-br] Consulta demorando 2 horas como resolvo.
Grande Eduardo....
Parabéns pela explanação...
Acredito que ajudou a muita gente, principalmente iniciantes como eu, a
compreender melhor o funcionamento do FB.
[ ]'s
Jáber Sancho Coelho de Lima
Cel: (66)9613-2594
Fax: (66)3426-2171
Msn: jabertecnico em hotmail.com
Skype: jabertecnico
Em 04/06/2011 19:19, Eduardo Bahiense escreveu:
> Olá Luciano
>
> Desculpe se chego atrasado nesta thread, mas uso o FB em ambientes de
> alta requisição e, por ter certeza de sua performance e segurança,
> sinto-me na obrigação de analisar esse caso.
> Primeiramente, permita-me organizar essa consulta, pois, código SQL
> deve ser tratado como qualquer linguagem de programação: indenta-se
> para dar melhor entendimento, especialmente se a submetemos a terceiros.
>
> select
> cm.codigo,
> cm.codigo_barras,
> cm.codigo_fabricante,
> cm.cod_fornecedor,
> cm.mercadoria,
> cf.fornecedor,
> Max(Case When(Gp.filial = 1) Then Gp.preco_g_vista End) As Preco_AS,
> Max(Case When(Gp.filial = 2) Then Gp.preco_g_vista End) As Preco_MT
> from
> cadastro_mercadorias cm
> inner join cadastro_fornecedor cf on (cf.codigo = cm.cod_fornecedor)
> Inner Join grade_produtos GP on (Gp.cod_produto = CM.codigo)
> Where
> exists (select
> cc.codigo_barras
> from
> cadastro_mercadorias cc
> where
> cc.codigo_barras = cm.codigo_barras
> group by
> 1
> having count(cc.codigo_barras) > 1
> )
> group by
> 1, 2, 3, 4, 5, 6
> order by
> cm.codigo_barras
>
> Bem, a primeira coisa que chama a atenção nessa consulta é o "order
> by", no 2º campo. Como o Eduardo J. já mencionou, o próprio "group by"
> já ordena, assim, um
> "group by 2,1,3,4,5,6", ou um
> select
> cm.codigo_barras,
> cm.codigo,
> ...
> group by
> 1, 2, 3, 4, 5, 6
>
> evitaria o "order by", resultando em melhor performance, especialmente
> se o resultado dessa consulta envolver milhares de linhas.
>
> Fora essa questão, a cláusula "select" está ok, nada a comentar.
> Quanto aos "joins", é preciso saber se há índices em:
> cadastro_fornecedor.codigo
> grade_produtos.cod_produto
> para que essas junções não tenha problema de performance.
> Outra coisa a se considerar é que "inner join" quando o lado direito
> possui pouca correlação, pode ser muito penoso.
> Se você está usando "inner join" é porque está esperando que haja
> produtos sem código de fornecedor ou sem código de grade_produto,
> assim, você poderia, testar a performance com "left join" com uma
> clasa "where" do tipo:
> where
> cm.cod_fornecedor is not null
> and CM.codigo is not null
> and exists(...)
>
> Verificadas essas questões, passamos para a cláusula "where" em si:
>
> Um "where exists(...)", por si só, obriga a busca natural, ou seja sem
> índices, assim, todos os registros de "cadastro_mercadorias" serão,
> obrigatoriamente lidos, e uma outra segunda consulta será executada
> (select do exists) para cada linha de "cadastro_mercadorias".
> Bem, considerando o fato de que cada linha em "cadastro_mercadorias"
> vai gerar um segunda consulta, esta deve ser cuidadosa quanto à
> performance, então, vamos dar uma olhada:
>
> select
> cc.codigo_barras
> from
> cadastro_mercadorias cc
> where
> cc.codigo_barras = cm.codigo_barras
> group by
> 1
> having count(cc.codigo_barras) > 1
>
> Primeiramente, temos que analisar se há um índice em
> "cadastro_mercadorias.codigo_barras", porque se não houver índice,
> para cada linha percorrida em "cadastro_mercadorias", haverá uma
> varredura em todas as linhas dessa mesma tabela para pesquisar esse
> "where".
> Verificado o índice, observe que exists(...) não depende de um campo,
> basta "select 1", ao invés de "select cc.codigo_barrsas". Não que isso
> seja determinante na performance, mas se estamos falando em otimizar...
> O group by neste subselect também é totalmente dispensável, se o
> construirmos dessa forma:
>
> where (
> select
> count(1)
> from
> cadastro_mercadorias cc
> where
> cc.codigo_barras = cm.codigo_barras
> ) > 1
>
> Se houver índices adequados, mesmo não sendo a melhor construção, você
> não deveria ter problemas de performance, e isso nos remete a uma
> afirmativa sua:
>
> "Ele vai retornar produtos com o codigo de barras duplicados. eu sei
> que deve ter SQLs mais simples para esse proposito só que agora achei
> interessante o porque o PostGreSQL ser tão mais veloz".
>
> Acho improvável que o PG consiga performance muito melhor nas mesmas
> condições de volume de dados e planejamento de índices. O mais
> provável é que você tenha movido dados do PG para o FB sem trazer o
> planejamento de índices, contudo, se o que você quer e identificar
> produtos com código de barras duplicados, dentro da estrutura inicial
> que você informou
>
> select
> cm.codigo_barras,
> cm.codigo,
> cm.codigo_fabricante,
> cm.cod_fornecedor,
> cm.mercadoria,
> cf.fornecedor,
> Max(Case When(Gp.filial = 1) Then Gp.preco_g_vista End) As Preco_AS,
> Max(Case When(Gp.filial = 2) Then Gp.preco_g_vista End) As Preco_MT
> from
> cadastro_mercadorias cm
> inner join cadastro_fornecedor cf on (cf.codigo = cm.cod_fornecedor)
> Inner Join grade_produtos GP on (Gp.cod_produto = CM.codigo)
> group by 1,2,3,4,5,6
> having count(*) > 1
>
> Observe apenas que você está pedindo se há codigos de barras duplicado
> para cada conjunto fornecedor/fabricante/mercadoria.
>
> Dá para conversar muito sobre tudo isso, mas já falei demais para um
> post.
>
> Sucesso,
>
> Eduardo
>
>
>
>
>
>
> ______________________________________________
> FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
> Para saber como gerenciar/excluir seu cadastro na lista, use:
> http://www.firebase.com.br/fb/artigo.php?id=1107
> Para consultar mensagens antigas: http://firebase.com.br/pesquisa
>
______________________________________________
FireBase-BR (www.firebase.com.br) - Hospedado em www.locador.com.br
Para saber como gerenciar/excluir seu cadastro na lista, use:
http://www.firebase.com.br/fb/artigo.php?id=1107
Para consultar mensagens antigas: http://firebase.com.br/pesquisa
Mais detalhes sobre a lista de discussão lista