Fórum Demora ao abrir um TClientDataSet #329501
15/09/2006
0
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
Curtir tópico
+ 0Posts
15/09/2006
Macario
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)
Gostei + 0
15/09/2006
Marco Salles
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
Gostei + 0
15/09/2006
Adrbrusc
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...
Gostei + 0
15/09/2006
Macario
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).
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)
Gostei + 0
16/09/2006
Raserafim
mas o que é sentido, o que significa e o que provoca o ´cursor e conexão ficam aguardando novas solicitações´.
Gostei + 0
16/09/2006
Adrbrusc
Muito obrigado mesmo...
Gostei + 0
17/09/2006
Marco Salles
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...
Gostei + 0
18/09/2006
Marco Salles
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:
No Botao Proximo: Isto é o Next
[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
Gostei + 0
18/09/2006
Macario
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.
Gostei + 0
18/09/2006
Marco Salles
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]
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)