Consulta SQL demorada quando passado parametro
07/01/2013
1
Pessoal,
Estou com um problema um tanto que "cabuloso"
Tenho a seguinte consulta SQL:
SELECT NFE_DATMOV, PNF_QTDPRD, PNF_VALIPI, PNF_VALSUB FROM INTNFE
INNER JOIN INTPNF ON (
INTNFE.NFE_CODEMP = INTPNF.PNF_CODEMP AND
INTNFE.NFE_CODFIL = INTPNF.PNF_CODFIL AND
INTNFE.NFE_CICFOR = INTPNF.PNF_CICFOR AND
INTNFE.NFE_SERNOT = INTPNF.PNF_SERNOT AND
INTNFE.NFE_NUMNOT = INTPNF.PNF_NUMNOT AND
INTNFE.NFE_CODTME = INTPNF.PNF_CODTME)
WHERE NFE_CODEMP = :pCodEmp AND NFE_CODFIL = :pCodFil AND
NFE_DATMOV < :pDatMov AND PNF_CODPRD = :pCodPrd
ORDER BY NFE_DATMOV DESC
Para um entendimento melhor seguem algumas explicações:
A) A tabela INTPNF armazena os produtos da nota fiscal de entrada
B) A tabela INTNFE armazena as notas fiscais de entrada (cabeça da nota)
C) O objetivo dessa consulta é encontrar a(s) ultima(s) entrada(s) (até uma determinada data) de um produto especificado em :pCodPrd
D) A ordenação no final é para seja por ordem decrescente de data do movimento
Utilizo um SQLDataSet para resultar essa consulta com o seguinte trecho de código:
A questão é, para alguns produtos, na maioria dos casos produtos que não possuem nenhum registro em INTPNF a consulta demora até 10 segundos para ser aberta.
Apos realizar vários e vários testes, consegui descobrir que se ao invés de enviar o código do produto como parâmetro eu manda-lo direto pelo SQL a consulta é executada rapidamente (tempo normal e aceitável).
Alguém poderia ajudar a explicar esse mistério?
Utilizo Delphi XE2, Banco de Dados Sql Server 2008 R2
A aplicação está na arquitetura de 3 camadas datasnap, porém realizei testes das mais diferentes formas e obtive o mesmo resultado em todas.
Atenciosamente,
Rodrigo Alves
Estou com um problema um tanto que "cabuloso"
Tenho a seguinte consulta SQL:
SELECT NFE_DATMOV, PNF_QTDPRD, PNF_VALIPI, PNF_VALSUB FROM INTNFE
INNER JOIN INTPNF ON (
INTNFE.NFE_CODEMP = INTPNF.PNF_CODEMP AND
INTNFE.NFE_CODFIL = INTPNF.PNF_CODFIL AND
INTNFE.NFE_CICFOR = INTPNF.PNF_CICFOR AND
INTNFE.NFE_SERNOT = INTPNF.PNF_SERNOT AND
INTNFE.NFE_NUMNOT = INTPNF.PNF_NUMNOT AND
INTNFE.NFE_CODTME = INTPNF.PNF_CODTME)
WHERE NFE_CODEMP = :pCodEmp AND NFE_CODFIL = :pCodFil AND
NFE_DATMOV < :pDatMov AND PNF_CODPRD = :pCodPrd
ORDER BY NFE_DATMOV DESC
Para um entendimento melhor seguem algumas explicações:
A) A tabela INTPNF armazena os produtos da nota fiscal de entrada
B) A tabela INTNFE armazena as notas fiscais de entrada (cabeça da nota)
C) O objetivo dessa consulta é encontrar a(s) ultima(s) entrada(s) (até uma determinada data) de um produto especificado em :pCodPrd
D) A ordenação no final é para seja por ordem decrescente de data do movimento
Utilizo um SQLDataSet para resultar essa consulta com o seguinte trecho de código:
SQLConsultaUltimaCompra.Close; SQLConsultaUltimaCompra.Params[0].AsString := pCodEmpresa; SQLConsultaUltimaCompra.Params[1].AsString := pCodFilial; SQLConsultaUltimaCompra.Params[2].AsString := pDataMovimento; SQLConsultaUltimaCompra.Params[3].AsString := pCodigoProduto; SQLConsultaUltimaCompra.Open;
A questão é, para alguns produtos, na maioria dos casos produtos que não possuem nenhum registro em INTPNF a consulta demora até 10 segundos para ser aberta.
Apos realizar vários e vários testes, consegui descobrir que se ao invés de enviar o código do produto como parâmetro eu manda-lo direto pelo SQL a consulta é executada rapidamente (tempo normal e aceitável).
SQLConsultaUltimaCompra.CommandText := 'SELECT NFE_DATMOV, PNF_QTDPRD, PNF_VALIPI, PNF_VALSUB FROM INTNFE '+ 'INNER JOIN INTPNF ON ( '+ 'INTNFE.NFE_CODEMP = INTPNF.PNF_CODEMP AND '+ 'INTNFE.NFE_CODFIL = INTPNF.PNF_CODFIL AND '+ 'INTNFE.NFE_CICFOR = INTPNF.PNF_CICFOR AND '+ 'INTNFE.NFE_SERNOT = INTPNF.PNF_SERNOT AND '+ 'INTNFE.NFE_NUMNOT = INTPNF.PNF_NUMNOT AND '+ 'INTNFE.NFE_CODTME = INTPNF.PNF_CODTME) '+ 'WHERE NFE_CODEMP = :pCodEmp AND NFE_CODFIL = :pCodFil AND '+ 'NFE_DATMOV < :pDatMov AND PNF_CODPRD = '+QuotedStr(CodigoProduto) ' ORDER BY NFE_DATMOV DESC SQLConsultaUltimaCompra.Params[0].AsString := pCodEmpresa; SQLConsultaUltimaCompra.Params[1].AsString := pCodFilial; SQLConsultaUltimaCompra.Params[2].AsString := pDataMovimento; SQLConsultaUltimaCompra.Open;
Alguém poderia ajudar a explicar esse mistério?
Utilizo Delphi XE2, Banco de Dados Sql Server 2008 R2
A aplicação está na arquitetura de 3 camadas datasnap, porém realizei testes das mais diferentes formas e obtive o mesmo resultado em todas.
Atenciosamente,
Rodrigo Alves
Responder
Posts
07/01/2013
Rodrigo tudo certo?
Em minhas experiências com bases de dados e muitas informações nelas, certa vez me deparei com um problema parecido... quando fui ver as tabelas relacionadas estavam sem índices adequados.
Já verificou isso?
Em minhas experiências com bases de dados e muitas informações nelas, certa vez me deparei com um problema parecido... quando fui ver as tabelas relacionadas estavam sem índices adequados.
Já verificou isso?
Responder
07/01/2013
Já, inclusive criei um index de acordo com o que o SQL Server estava sugerindo, e a melhoria no tempo de resposta da consulta foi 0.
Devolvo a seguinte pergunta: - Se fosse um problema de index não estaria lento das duas formas? Tanto passando o parâmetro como passando no SQL Diretamente?
Devolvo a seguinte pergunta: - Se fosse um problema de index não estaria lento das duas formas? Tanto passando o parâmetro como passando no SQL Diretamente?
Responder
07/01/2013
Nem sempre... no meu caso... quando rodava no Java era lento e no sql não tão lento.
Quando os índices foram criados ficou tudo na mesma velocidade.
Quando os índices foram criados ficou tudo na mesma velocidade.
Responder
07/01/2013
Acabei esquecendo de perguntar...
Já tentou rodar com DbxConnection ao invéis de usar os componentes visuais?
Já tentou rodar com DbxConnection ao invéis de usar os componentes visuais?
Responder
07/01/2013
Correto, já vi um caso assim, porem observe que não estou fazendo testes no SQL Management e no Delphi.
Nos testes aplicados todos são executados a partir do Delphi, e é justamente isso que está me intrigando, pois acredito que deveriam ter comportamentos iguais. Porque até onde entendo esses parâmetros serão convertidos para linguagem SQL e posteriormente executados no banco (acredito que isso é trabalho do Driver DBX), porem o que faço quando mando o SQL direto é poupar o trabalho de conversão. Não sei se essa colocação é 100% o que posso dizer é que estão produzindo resultados bastante diferentes com relação ao tempo de resposta.
Nos testes aplicados todos são executados a partir do Delphi, e é justamente isso que está me intrigando, pois acredito que deveriam ter comportamentos iguais. Porque até onde entendo esses parâmetros serão convertidos para linguagem SQL e posteriormente executados no banco (acredito que isso é trabalho do Driver DBX), porem o que faço quando mando o SQL direto é poupar o trabalho de conversão. Não sei se essa colocação é 100% o que posso dizer é que estão produzindo resultados bastante diferentes com relação ao tempo de resposta.
Responder
08/01/2013
Faça o seguinte, se voce tem o codigo fonte do delphi, coloque a unit Data.DBXDBReaders.pas dentro do seu projeto e compile!
Aqui estava com um bug justamente nisso, como o delphi trafega dados via json entre o clientes e depois converte esse processo estava demorando bastante, quando coloquei a unit no meu projeto ficou perfeito, acho que a .dcu que vem com ele deve estar com algum bug.
Aqui estava com um bug justamente nisso, como o delphi trafega dados via json entre o clientes e depois converte esse processo estava demorando bastante, quando coloquei a unit no meu projeto ficou perfeito, acho que a .dcu que vem com ele deve estar com algum bug.
Responder
08/01/2013
Problema resolvido com a criação de um index no banco, eu acreditava que era um BUG no Delphi XE2 por mostrar comportamentos diferentes em situações aparentemente parecidas, porem existe diferença na execução dos dois comandos, passando poro parâmetro e passando direto no SQL.
Index criado, problema resolvido!
Por curiosidade o index criado foi PNF_CODEMP+PNF_CODFIL+PNF_CODPRD
Obrigado aos que ajudaram na solução desse problema.
Index criado, problema resolvido!
Por curiosidade o index criado foi PNF_CODEMP+PNF_CODFIL+PNF_CODPRD
Obrigado aos que ajudaram na solução desse problema.
Responder
Clique aqui para fazer login e interagir na Comunidade :)