Fórum Demora ao abrir um TClientDataSet #329501

15/09/2006

0

Pessoal,

Estou usando BDS 2006 e SQL Server 2005 utilizando DBExpress.

Criei um DataModule onde adicionei um TSQLConnection, TSQLDataSet, TDataSetProvider, TClientDataSet e um TDataSource.

A tabela que configurei tem 576000 registros e é a de CEP dos correios (antiga e desatualizada, mas quebra um galho). Faço a ligação de todos os componentes para acessar os dados e quando vou Ativar o componente TClientDataSet fica uns 5 minutos para se tornar ativa. O que pode ser tanta demora ??? Tem como configurar alguma propriedade para melhorar isso.

Obs.: No TSQLDataSet qdo dou um Activate = True é rapidinho, mas qdo vou ativar pelo ClientDataSet demora muito.

Obrigado


Adrbrusc

Adrbrusc

Responder

Posts

15/09/2006

Macario

Ola Adriano.


O SQLDataSet é unidierecional(veja este topico [url=http://forum.clubedelphi.net/viewtopic.php?t=68831&highlight=unidirecional+sqldataset]Trabalhando com ClientDataSet[/url].

O ClientDataSet faz um cache dos dados em memoria, no seu caso a demora ocorre pelo elevado numero de registros.

Evite usar instrucoes tais como ´select * from tabela´ pois isso alem de nao ser uma boa pratica de programacao(client/server) gera um trafego enorme na rede.


Creio que voce nao necessite de toda a tabela CEP em cache, mas este seu caso serve de exemplo quando no futuro voce se deparar com uma situacao parecida.

Qualquer duvida, post novamente.

Espero ter ajudado.

8)


Responder

Gostei + 0

15/09/2006

Marco Salles

O que pode ser tanta demora ??? Tem como configurar alguma propriedade para melhorar isso.


tem sim..

atualmente voce esta fazendo assiM

1 – Sem usar PacketRecords Todos os dados retornados pelo Select foram empacotados e jogados na memória (Data) do ClienDataSet. Nenhum recurso do servidor, incluindo conexão e cursor, fica preso. No entanto, o tempo necessário e tráfego de rede usado para transferir o packet é maior.

a idéia é instruir ao servidor de aplicação que “empacote e envie dados por demanda”. Para que acessar 576000 registros se ningume le todos ao mesmo tempo


2)– Usando PacketRecords com FetchOnDemand ativado -Configure o packet size como “30”, o que indica que os registros serão empacotados de 30 em trinta. O próprio ClientDataSet detecta quando mais registros são necessário e traz por demanda (daí o nome FetchOnDemand). Isso pode acontecer tanto por necessidade do usuário (confirme isso navegando no DBGrid para baixo) ou programaticamente (via chamadas subseqüentes ao método Next). Observe que cada Fetch envolve, lógico, uma chamada ao servidor SQL.

Vantagens::: A solução é mais otimizada para grandes resultsets,

Desvantagens:
consumir mais recursos do BD, pois o cursor e conexão ficam presos aguardando novas solicitações de packet.

Propriedade 

ClientDataSet1.FetchOnDemand :=True e 

ClientDataSet1.PacketRecords := escolha un numero ;


3) Usando PacketRecords com FetchOnDemand desativado - Configure o packet size como “3”, o que indica que os registros serão empacotados de 10 em 10. A diferença em não usar o FetchOnDemand é que você deve solicitar novos pacotes de dados, através do método GetNextPacket do CDS (faça isso no botão). Faça um teste navegando até o último registro do DBGrid, observe que ele “trava” no Decimo. Clicando no botão GetNextPacket, mais dez registros serão trazidos. Cada Fetch envolve, lógico, uma chamada ao servidor SQL.

Novamente a vantagem:A solução é mais otimizada para grandes resultsets,

Desvanntagen:
mais vai consumir mais recursos do BD, pois o cursor e conexão ficam presos aguardando novas solicitações de packet.


ClientDataSet1.FetchOnDemand :=False e 

ClientDataSet1.PacketRecords := escolha un numero ;

usar medodo GetNextPacket nun Botão por exemplo: 

  ClientDataSet1.GetNextPacket;


espero ter sido claro e util


Responder

Gostei + 0

15/09/2006

Adrbrusc

Obrigado Macario....

Então só de eu ativar o ClientDataSet ele já me traz todos os registros, indiferente de eu apresentá-los num grid ou não ???? O ideal seria montar um comando parecido ?

//Consulta por CEP
Select * from Tabela
where CEP = :nCEP

mas se eu precisar de uma consulta por endereço eu devo alterar em tempo de execução o código do TSQLDataset ? É isso ?

//Consulta por endereço
Select * from Tabela
where ENDERECO = :sEndereco


Obrigado pela ajuda...


Responder

Gostei + 0

15/09/2006

Macario

O ideal seria montar um comando parecido ? //Consulta por CEP Select * from Tabela where CEP = :nCEP



Sim este seria o metodo ideal. Pesquisas exatas e o ´forte´ de instrucoes SQL, mas veja mesmo assim vc pode ter uma pequena demora no retorno, neste caso voce precisaria de auxilio de indice para aumentar a performance da pesquisa. Se vc buscar por CEP e demorar crie um indice pelo campo CEP(creio que esta tabela ja tenha um).


mas se eu precisar de uma consulta por endereço eu devo alterar em tempo de execução o código do TSQLDataset ? É isso ? //Consulta por endereço Select * from Tabela where ENDERECO = :sEndereco


Se vc tiver conhecimento sobre Stored Procedure, voce pode criar uma para efetuar a pesquisa onde voce estaria passando parametros, como por exemplo: o tipo da consulta (por CEP, Endereco, etc) e o valor da pesquisa(o CEP propriamente dito, ou o Nome da rua, al. av..etc)

Qualquer duvida aqui estamos colega.
8)


Responder

Gostei + 0

16/09/2006

Raserafim

Marco Salles, eu não conhecia o PacketRecords e o FetchOnDemand, e achei interessante, e valeu pela explicação.

mas o que é sentido, o que significa e o que provoca o ´cursor e conexão ficam aguardando novas solicitações´.


Responder

Gostei + 0

16/09/2006

Adrbrusc

Obrigado Macario e Marcos Salles estarei testando as sugestões apresentadas por vcs e em seguida colocarei o resultado aqui...

Muito obrigado mesmo...


Responder

Gostei + 0

17/09/2006

Marco Salles

mas o que é sentido, o que significa e o que provoca o ´cursor e conexão ficam aguardando novas solicitações´.


Ora , imagine que vce coloque este executavel na rede , e que voce acesse de várias estaçoes da sua rede Local...Cada aplicaçao , usando o modelo anterior <cursor e conexao ativos> , via consumir uma conexão no Banco de Dados. O que pode ser prejuducar a Scalabilidade a performace e o ambiente de Rede. Aonde poderemos ter varios clientes acessando simultaneamnete o Servidor de Banco De Dados , alem do de limites de conexoes geralmente impostas pelo Servidor...


Responder

Gostei + 0

18/09/2006

Marco Salles

Obrigado Macario e Marcos Salles estarei testando as sugestões apresentadas por vcs e em seguida colocarei o resultado aqui... Muito obrigado mesmo...


acho que seria de muita importancia voce colocar o resultado de sua experiencia aqui... Limitar a quantidade de registros retornados numa consulta , é sem duvida uma boa pratica , esta , acho que ninguem duvida dos frutos.
... Porem a utilização , do Bloco é algo ainda muito pouco utilizado e acho
que seria interresante voce fazer a Limitação do Sql , juntamente com a idéia dos Blocos

Veje um exemplo:

1)No Objeto inspector do Cds faça:
FetchOnDemand em False;
PacketRecords = 10

2)coloque dois botoes e um edit no seu formulario e faça:

no Botão consultars:

procedure TForm1.Button1Click(Sender: TObject); begin seuDataqry.SQL.Clear; seuDataqry.SQL.Add(´SELECT CEP , SeusCampos FROM SuaTabela´); seuDataqry.SQL.Add(´where (Upper(Cep) Like :pCep)´); seuDataqry.SQL.Add(´Order By Cep´); seuDataqry.ParamByName(´pCep´).AsString:=AnsiUpperCase(Edit1.Text)+´¬´; seuDataqry.ExecSQL(false); // ou //seuDataquery.open; **depende do tipo do SeuDataQuery cds.Close; cds.Open; end;


No Botao Proximo: Isto é o Next

procedure TForm1.Button2Click(Sender: TObject); begin cds.GetNextPacket; end;


[b:cbd6a979c6]voce vera como os blocos serão trazidos de dez em dez[/b:cbd6a979c6]

Detalhe importante ...
Como voce colocou
FetchOnDemand em False;
PacketRecords = 10
nen precisa usar Where na sua clausula incial , pois ao Abrir a consulta , voce ja tera os blocos por demanda.. Isto é , inicialmente serao trazidos os dez primeiros , o que deve ser um Ganho muito grande em performace

IMportante: Não use , para esta finalidade o ComandText do cds para passar as instruçoes sql. Apesar de ser um boa prática , nesta estrutura , não funciona corretamente... Use o proprio SeuDataSql para consultar no Banco


Responder

Gostei + 0

18/09/2006

Macario

[quote:f59978632e=´Marco Salles´]
IMportante: Não use , para esta finalidade o ComandText do cds para passar as instruçoes sql. Apesar de ser um boa prática , nesta estrutura [b:f59978632e], não funciona corretamente[/b:f59978632e]... Use o proprio SeuDataSql para consultar no Banco[/quote:f59978632e]

Ola Marcos, bom dia.

Voce nos diria qual problema ocorre com a utilizacao do commandtext do ClientDataSet?

Grato.


Responder

Gostei + 0

18/09/2006

Marco Salles

Voce nos diria qual problema ocorre com a utilizacao do commandtext do ClientDataSet?


Minha experiecia pessoal demostra isto.. [b:5932ba91cf]Mas voce mesmo pode testar , e deve testar[/b:5932ba91cf]
Acredito eu que a explicação é a seguinte:


a idéia que de empacatar e enviar dados por demanda tem um preço... Como foi dito :
[b:5932ba91cf]é necessário manter o cursor e conexão ativos durante todo o processo. [/b:5932ba91cf]Pelo simples motivo , que ao fazer nova solicitação ao banco , o mesmo saiba atraves de algum mecanismo interno
< [b:5932ba91cf]que acredito eu , seja exatamente fornecido por algum ponteiro , que nesse caso é o cursor [/b:5932ba91cf]>
a partir de qual registro ele deve efetuar o[b:5932ba91cf] fecth [/b:5932ba91cf]para o Client.
Isto evita que dados sejam [b:5932ba91cf]reenviados[/b:5932ba91cf] que com certeza teríams um reduntancia , alem de ganhar tempo (Imagine em cada solicitação ter que fazer tudo de novo ) :cry: :cry: :cry:

Quando se usa o ComantText do sql , por construção interna esse ponteiro que armazena exatamente esta localização , é cetado e portanto e perde-se esta referencia.

P:S
Em aplicaçoes 3 camadas é necessário informar ao Provider a partir de qual registro ele deve efetuar o fecth para o Client...
isto é feito geralmente no no evento BeforeGetRecords do CDS , como consta no Helph do Delphi.

mas como eu disse antes : [b:5932ba91cf]é importante Testar e não somente confiar[/b:5932ba91cf]


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar