Dúvida com o ClientDataSet
Seguinte, estou utilizando um ClientDataSet ligado a um Query que realiza uma consulta.
Digamos que eu traga todos os registros da tabela com essa consulta (500 registros) da seguinte forma:
A consulta demora mais do que se eu usasse somente o Query. Pelo que parece ao abrir o ClientDataSet ele abre a Query que demora um pouco, depois ele ´copia´ os registros da Query para o ClientDataSet.
Com isso ele demora mais do que com o Query... eu uso essa opção pois eu posso desconectar da base e não ficar com o registro amarrado... enfim... será que existe algo a ser feito em relação a isso... ou é assim mesmo?
Estou usando o PostgreSQL com Zeos.
PS. O ClientDataSet funciona numa boa com o Zeos desde que eu não utilize o PacketRecords
Digamos que eu traga todos os registros da tabela com essa consulta (500 registros) da seguinte forma:
BuscaCDS.Close; QBusca.Close; QBusca.SQL.Clear; QBusca.SQL.Add(´select e.codigo,e.estoque,itm.itm_descricao, un.medida, cast(upper(c.descricao) as varchar) as categoria from almoxarifado.estoque e´); QBusca.SQL.Add(´join materiais.itens itm on itm.id = e.fk_item´); QBusca.SQL.Add(´join almoxarifado.unidades_medidas un on e.fk_unidade = un.id´); QBusca.SQL.Add(´join almoxarifado.categorias_materiais c on c.codigo = e.fk_categoria_material´); QBusca.SQL.Add(´where e.fk_almoxarifado = :fk_almoxarifado and c.fk_almoxarifado = :fk´); QBusca.SQL.Add(´order by e.codigo´); QBusca.Params[0].AsInteger := VFk_Almoxarifado; QBusca.Params[1].AsInteger := VFk_Almoxarifado; BuscaCDs.Open;
A consulta demora mais do que se eu usasse somente o Query. Pelo que parece ao abrir o ClientDataSet ele abre a Query que demora um pouco, depois ele ´copia´ os registros da Query para o ClientDataSet.
Com isso ele demora mais do que com o Query... eu uso essa opção pois eu posso desconectar da base e não ficar com o registro amarrado... enfim... será que existe algo a ser feito em relação a isso... ou é assim mesmo?
Estou usando o PostgreSQL com Zeos.
PS. O ClientDataSet funciona numa boa com o Zeos desde que eu não utilize o PacketRecords
Marcelo_mileris
Curtidas 0
Respostas
Brunolspp
21/11/2006
o correto e vc passar os parametros e td mais pelo clientdataset..
vc pode obter mais exemplos e uma apostila q mostra alguams tecnicas de desenvolvimento clientdataset em:
http://cc.borland.com/Author.aspx?ID=795118
Abração
vc pode obter mais exemplos e uma apostila q mostra alguams tecnicas de desenvolvimento clientdataset em:
http://cc.borland.com/Author.aspx?ID=795118
Abração
GOSTEI 0
Marcelo_mileris
21/11/2006
Vc diz utilizar a propriedade CommandText do ClientDataSet?
Isso faz com que a consulta seja realizada diretamente no ClientDataSet e não como eu expliquei no primeiro post?
Isso faz com que a consulta seja realizada diretamente no ClientDataSet e não como eu expliquei no primeiro post?
GOSTEI 0
Brunolspp
21/11/2006
vc pode usar o comando ate na query, poreme parametrizar e não criar dinamicamente.. ou se criar, fazer o fecth params no clientdataset e executar a passagem de parametros pelo CDS bem como a abertura dos resultados também
Abração
Abração
GOSTEI 0
Marcelo_mileris
21/11/2006
Ok... cheguei ao seguinte código:
Foi dessa forma que vc se referiu?
BuscaCDS.Close; QBusca.Close; QBusca.SQL.Clear; QBusca.SQL.Add(´select e.codigo,e.estoque,itm.itm_descricao, un.medida, cast(upper(c.descricao) as varchar) as categoria from almoxarifado.estoque e´); QBusca.SQL.Add(´join materiais.itens itm on itm.id = e.fk_item´); QBusca.SQL.Add(´join almoxarifado.unidades_medidas un on e.fk_unidade = un.id´); QBusca.SQL.Add(´join almoxarifado.categorias_materiais c on c.codigo = e.fk_categoria_material´); QBusca.SQL.Add(´where e.fk_almoxarifado = :fk_almoxarifado and c.fk_almoxarifado = :fk´); QBusca.SQL.Add(´order by e.codigo´); BuscaCDS.FetchParams; BuscaCDS.Params[0].AsInteger := VFk_Almoxarifado; BuscaCDS.Params[1].AsInteger := VFk_Almoxarifado; BuscaCDS.Open;
Foi dessa forma que vc se referiu?
GOSTEI 0
Brunolspp
21/11/2006
sim.. a parte final sim..
mas pq vc naum deixa o comando direto na query e so passa os parametros pelo cds, dai é só
BuscaCDS.Close;
BuscaCDS.Params[0].AsInteger := VFk_Almoxarifado;
BuscaCDS.Params[1].AsInteger := VFk_Almoxarifado;
BuscaCDS.Open;
abração
mas pq vc naum deixa o comando direto na query e so passa os parametros pelo cds, dai é só
BuscaCDS.Close;
BuscaCDS.Params[0].AsInteger := VFk_Almoxarifado;
BuscaCDS.Params[1].AsInteger := VFk_Almoxarifado;
BuscaCDS.Open;
abração
GOSTEI 0
Marcelo_mileris
21/11/2006
Eu não deixo a instrução direto pois eu monto ela conforme for selecionado a opção de busca... essa instrução é uma delas...
Agradeço a ajuda... realmente ficou um pouco mais rápido o ClientDataSet para trazer os resultados.
Agradeço a ajuda... realmente ficou um pouco mais rápido o ClientDataSet para trazer os resultados.
GOSTEI 0
Marcelo_mileris
21/11/2006
Esqueci de perguntar... se eu fizer várias buscas... montando as instruções dinamicamente... eu preciso limpar os parâmetros também... ou não implica em nada???
GOSTEI 0
Titanius
21/11/2006
Bem, a principio, quando você muda o CommandText, os parametros são zerados... pelo menos eu nunca precisei limpa-los :D
[]s
[]s
GOSTEI 0
Brunolspp
21/11/2006
no clientdataset é preciso limpar os parametros ou fazer o fetchparams de novo..
para construção de sqldinamico vc pode usar o clientdataset tb..
e so habilitar a opção allowcommandtext com datasetprovider..
se clientdataset for so de consulta, desabilita a propriedade getmetadata da query q melhora a performance tb
abração
para construção de sqldinamico vc pode usar o clientdataset tb..
e so habilitar a opção allowcommandtext com datasetprovider..
se clientdataset for so de consulta, desabilita a propriedade getmetadata da query q melhora a performance tb
abração
GOSTEI 0
Marco Salles
21/11/2006
Acho que o problema é conceitual...
O clientDataSet armazena tudo na memória , isto faz com que a aplicacção seje responsável pelo cache dos dados... Todos os dados de uma consulta são trazidos para a memoria
Quando se abre uma query, é o BDE que coordena a busca dos dados, so que ele não coloca todos os dados de uma so vez...
Para entender esta diferença , vamos supor que voce tenha uma tabela com muitos registros e um botão que coloque a query no ultimo registro(método last) .. Abra a aplicaçãoe , imediatamente apos ser mostrado o primeiro registro, pare o servidor da aplicação e click no botão... Voce receberá uma exceção...
Outra coisa muito importante , o tempo que voce espera usando uma query com o BDE , para abrir uma aplicação desse tipo é muito menor que o tempo que voce espera para abrir uma aplicação usando o clientDataSet
Existem alem de outras tecnicas de meçlhorar a performance do ClientDatset , voce definir o numero de registros que se deseja trazer , em cada operação utilizando o clientedataset.. Esta também é uma boa opção
O clientDataSet armazena tudo na memória , isto faz com que a aplicacção seje responsável pelo cache dos dados... Todos os dados de uma consulta são trazidos para a memoria
Quando se abre uma query, é o BDE que coordena a busca dos dados, so que ele não coloca todos os dados de uma so vez...
Para entender esta diferença , vamos supor que voce tenha uma tabela com muitos registros e um botão que coloque a query no ultimo registro(método last) .. Abra a aplicaçãoe , imediatamente apos ser mostrado o primeiro registro, pare o servidor da aplicação e click no botão... Voce receberá uma exceção...
Outra coisa muito importante , o tempo que voce espera usando uma query com o BDE , para abrir uma aplicação desse tipo é muito menor que o tempo que voce espera para abrir uma aplicação usando o clientDataSet
Existem alem de outras tecnicas de meçlhorar a performance do ClientDatset , voce definir o numero de registros que se deseja trazer , em cada operação utilizando o clientedataset.. Esta também é uma boa opção
GOSTEI 0
Brunolspp
21/11/2006
realmente o uso do CDS é mto abrangente e como o colega falow existem varios fatores que influenciam na performance
eu deixei varios exemplos praticos de tecnicas com codigo fonte do q usei em varios sistemas comerciais de alta performance, requisição e disponibilidade, td baseado em datasnap e 99¬ em BSS.
Tem bastante coisa la rpa ajudar
eis o link: http://cc.borland.com/Author.aspx?ID=795118
e no mais estou aki para o que precisar
;)
Abração
eu deixei varios exemplos praticos de tecnicas com codigo fonte do q usei em varios sistemas comerciais de alta performance, requisição e disponibilidade, td baseado em datasnap e 99¬ em BSS.
Tem bastante coisa la rpa ajudar
eis o link: http://cc.borland.com/Author.aspx?ID=795118
e no mais estou aki para o que precisar
;)
Abração
GOSTEI 0
Marcelo_mileris
21/11/2006
Não sei se vai ser válido eu postar os resultados porém ai estão:
- Base de dados Firebird com 65031 registros (Claro que ninguem (acho eu né :D) faria uma consulta trazendo toda essa quantidade de registros... porém somente assim consegui ver a diferença de tempo)
[b:0f910ec8da]Componentes:[/b:0f910ec8da]
IBDatabase -> TIBTransaction -> IBQuery - DataSetProvider -> ClientDataSet
Consulta com o SQL direto na IBQuery sendo aberta pelo ClientDataSet:
Tempo: 00:02:11 (Dois minutos e 11 segundos)
Consulta com o SQL direto no CommandText do ClientDataSet:
Tempo: 00:01:41 (1 minuto e 41 segundos)
---
Alterando as propriedades ProviderFlags dos Fields adicionados no ClientDataSet (exceto chave primária) para:
[b:0f910ec8da]pfInUpdate [/b:0f910ec8da]- True
[b:0f910ec8da]pfInWhere[/b:0f910ec8da] - False
[b:0f910ec8da]pfInKey[/b:0f910ec8da] - False
[b:0f910ec8da]pfHidden[/b:0f910ec8da] - False
Chave Primária:
[b:0f910ec8da]pfInUpdate [/b:0f910ec8da]- True
[b:0f910ec8da]pfInWhere[/b:0f910ec8da] - True
[b:0f910ec8da]pfInKey[/b:0f910ec8da] - True
[b:0f910ec8da]pfHidden[/b:0f910ec8da] - False
Alterando também o UpdateMode do DataSetProvider para [b:0f910ec8da]upWhereKeyOnly[/b:0f910ec8da]
Tempo: 00:01:37 (1 minuto e 37 segundos)
Levando em conta o tempo de retorno com cada uma das configurações... ficou claro que o ClientDataSet com algumas configurações fica quase duas vezes mais rápido.
Agora o porque que mudando aquelas ´flags´ ele fica mais rápido eu não sei... somente me falaram que assim ficaria mais rápido porém não souberam me explicar direito... se alguem souber
- Base de dados Firebird com 65031 registros (Claro que ninguem (acho eu né :D) faria uma consulta trazendo toda essa quantidade de registros... porém somente assim consegui ver a diferença de tempo)
[b:0f910ec8da]Componentes:[/b:0f910ec8da]
IBDatabase -> TIBTransaction -> IBQuery - DataSetProvider -> ClientDataSet
Consulta com o SQL direto na IBQuery sendo aberta pelo ClientDataSet:
Tempo: 00:02:11 (Dois minutos e 11 segundos)
Consulta com o SQL direto no CommandText do ClientDataSet:
Tempo: 00:01:41 (1 minuto e 41 segundos)
---
Alterando as propriedades ProviderFlags dos Fields adicionados no ClientDataSet (exceto chave primária) para:
[b:0f910ec8da]pfInUpdate [/b:0f910ec8da]- True
[b:0f910ec8da]pfInWhere[/b:0f910ec8da] - False
[b:0f910ec8da]pfInKey[/b:0f910ec8da] - False
[b:0f910ec8da]pfHidden[/b:0f910ec8da] - False
Chave Primária:
[b:0f910ec8da]pfInUpdate [/b:0f910ec8da]- True
[b:0f910ec8da]pfInWhere[/b:0f910ec8da] - True
[b:0f910ec8da]pfInKey[/b:0f910ec8da] - True
[b:0f910ec8da]pfHidden[/b:0f910ec8da] - False
Alterando também o UpdateMode do DataSetProvider para [b:0f910ec8da]upWhereKeyOnly[/b:0f910ec8da]
Tempo: 00:01:37 (1 minuto e 37 segundos)
Levando em conta o tempo de retorno com cada uma das configurações... ficou claro que o ClientDataSet com algumas configurações fica quase duas vezes mais rápido.
Agora o porque que mudando aquelas ´flags´ ele fica mais rápido eu não sei... somente me falaram que assim ficaria mais rápido porém não souberam me explicar direito... se alguem souber
GOSTEI 0
Marco Salles
21/11/2006
Agora o porque que mudando aquelas ´flags´ ele fica mais rápido eu não sei... somente me falaram que assim ficaria mais rápido porém não souberam me explicar direito... se alguem souber
eu não trabalho com os IB ,[b:6d7803019d] mas a explicação com certeza é a mesma encontrada , quando se trabalha com os componentes DbExpress[/b:6d7803019d]
Se no IB voce tiver a oportunidade de colocar um Componente que irá ´visualizar´ e detalhar como esta sendo processada o seu Sql , voce podera chegar a algumas conclusões .. [b:6d7803019d]No DbExpress esse componente se chama TSqlMonitor e explicação seria assim:[/b:6d7803019d]
Coloque por curiosidade um TSqlMonitor na sua aplicação (so por curiosidade) e [b:6d7803019d]veje[/b:6d7803019d] o log gerado pela consulta Sql... Voce vera que definidindo os flags , voce estara parametrizando a sua instrução Sql , que sera reolvida pelo DataSetProvider....
[b:6d7803019d]Em outra palavras voce trocara menos informação com o Servidor..[/b:6d7803019d]
Ao analizar o log gerado pelo SqlMonitor , voce podera observar como sua [b:6d7803019d]instrução Sql ´Gerada´ < que sera resolvida pelo DataSetProvider > conterá menos ´campos´[/b:6d7803019d] , tanto na clausula Update como na clausula Where e portanto sera processada muito mais rapidamente pelo servidor.
GOSTEI 0
Titanius
21/11/2006
Não sei se vai ser válido eu postar os resultados
ClientDataSet (exceto chave primária) para:
[b:490fcc1d46]pfInUpdate [/b:490fcc1d46]- True
[b:490fcc1d46]pfInWhere[/b:490fcc1d46] - False
[b:490fcc1d46]pfInKey[/b:490fcc1d46] - False
[b:490fcc1d46]pfHidden[/b:490fcc1d46] - False
Chave Primária:
[b:490fcc1d46]pfInUpdate [/b:490fcc1d46]- True
[b:490fcc1d46]pfInWhere[/b:490fcc1d46] - True
[b:490fcc1d46]pfInKey[/b:490fcc1d46] - True
[b:490fcc1d46]pfHidden[/b:490fcc1d46] - False
Alterando também o UpdateMode do DataSetProvider para [b:490fcc1d46]upWhereKeyOnly[/b:490fcc1d46]
Agora o porque que mudando aquelas ´flags´ ele fica mais rápido eu não sei... somente me falaram que assim ficaria mais rápido porém não souberam me explicar direito... se alguem souber
Bem, isto é meio que óbvio, pois setando o DataSetProvider para upWhereKeyOnly, na hora que ele vai gerar o SQL ele gera levando em conta a chave primária, ou seja, o campo que você marcar como pfInKey.
O ideal é você marcar lá no ClientDataSet, como [b:490fcc1d46]pfInKey := True e pfInWhere := True[/b:490fcc1d46] todos os campos que fazem parte de sua [b:490fcc1d46]chave primária[/b:490fcc1d46], assim o retorno será muito mais rápido.
Espero ter sido claro..
[]s
GOSTEI 0
Brunolspp
21/11/2006
eita galera afiada!!!!
:D
:D
GOSTEI 0
Júlio Ferreira
21/11/2006
Meus amigos do fórum!
Esse esqueminha do pfInKey para a chave primária está realmente correto. Mas comigo ainda não está funcionando...
Minha situação é um pouco diferente, pois meu servidor disponibilizar o ProviderDataSet através de uma conexão via ADOConnection e realizando uma query através de um ADOQuery.
O lado do cliente está normal, com um TClientDataSet configurado com o ProviderFlags desse mesmo jeito discutido neste tópico. Mas ainda assim, não está funcionando.
Existe alguma dica diferente para a minha situação ou ela simplesmente não funciona...
Esse esqueminha do pfInKey para a chave primária está realmente correto. Mas comigo ainda não está funcionando...
Minha situação é um pouco diferente, pois meu servidor disponibilizar o ProviderDataSet através de uma conexão via ADOConnection e realizando uma query através de um ADOQuery.
O lado do cliente está normal, com um TClientDataSet configurado com o ProviderFlags desse mesmo jeito discutido neste tópico. Mas ainda assim, não está funcionando.
Existe alguma dica diferente para a minha situação ou ela simplesmente não funciona...
GOSTEI 0