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:

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

Lucas Chagas

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?
Responder

07/01/2013

Integral Ltda

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?


Responder

07/01/2013

Lucas Chagas

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.
Responder

07/01/2013

Lucas Chagas

Acabei esquecendo de perguntar...

Já tentou rodar com DbxConnection ao invéis de usar os componentes visuais?
Responder

07/01/2013

Integral Ltda

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.
Responder

08/01/2013

Daniel Santos

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.
Responder

08/01/2013

Integral Ltda

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.
Responder