Demora para desconectar banco
Amigos,
Estou enfentando um problema de demora para desconectar o banco de dados. O banco de dados, ainda teste está pequeno +- 700k, e até ontem estava funcionando bem, porém hoje começou a demorar muito para desconectar (uns 2 ou 3 minutos) em modo local.
Avaliando a execução do programa, vejo que a demora está na linha:
db.Connected := False;
Este comando está dentro do evento onDestroy do datamodule.
Já executei um gfix para ver se o banco está com problema, mas está tudo ok. O que poderia ser?
Estou enfentando um problema de demora para desconectar o banco de dados. O banco de dados, ainda teste está pequeno +- 700k, e até ontem estava funcionando bem, porém hoje começou a demorar muito para desconectar (uns 2 ou 3 minutos) em modo local.
Avaliando a execução do programa, vejo que a demora está na linha:
db.Connected := False;
Este comando está dentro do evento onDestroy do datamodule.
Já executei um gfix para ver se o banco está com problema, mas está tudo ok. O que poderia ser?
Aerreira
Curtidas 0
Respostas
Vinicius2k
29/09/2004
Colega,
É a primeira vez que presencio este problema, mas no meu entender esta linha não é necessária...
Na destruíção do Data Module, consequentemente seus ´filhos´ serão antes dele e o destroy do IBDatabase, faz todo o procedimento de fechamento de DataSets e desconexão automaticamente...
Pessoalmente, nunca me desconectei do banco ao fechar a aplicação... posso até estar errado neste procedimento...
Como não tenho certeza, embasei minha resposta no destructor do IBDatabase, veja :
Espero ter ajudado...
T+
É a primeira vez que presencio este problema, mas no meu entender esta linha não é necessária...
Na destruíção do Data Module, consequentemente seus ´filhos´ serão antes dele e o destroy do IBDatabase, faz todo o procedimento de fechamento de DataSets e desconexão automaticamente...
Pessoalmente, nunca me desconectei do banco ao fechar a aplicação... posso até estar errado neste procedimento...
Como não tenho certeza, embasei minha resposta no destructor do IBDatabase, veja :
destructor TIBDatabase.Destroy; var i: Integer; begin if FIBLoaded then begin IdleTimer := 0; if FHandle <> nil then try Close; except ForceClose; end; for i := 0 to FSQLObjects.Count - 1 do if FSQLObjects[i] <> nil then SQLObjects[i].DoDatabaseFree; RemoveSQLObjects; RemoveTransactions; FInternalTransaction.Free; FreeMem(FDPB); FDPB := nil; FDBParams.Free; FSQLObjects.Free; FUserNames.Free; FTransactions.Free; FEventNotifiers.Free; FSchema.Free; end; FGDSLibrary := nil; inherited Destroy; end;
Espero ter ajudado...
T+
GOSTEI 0
Aerreira
29/09/2004
Na destruíção do Data Module, consequentemente seus ´filhos´ serão antes dele e o destroy do IBDatabase, faz todo o procedimento de fechamento de DataSets e desconexão automaticamente...
Bom então não preciso tomar nenhum procedimento para fechar o banco, perfeito. Mas acho que meu problema é outro, pois estava funcionando mesmo com o db.connected := false, e agora coloquei todo o conteúdo do OnDestroy do DataModule como comentário e minha aplicação continua travando na saida.
Nas propriedades do FireBird Server ficam constando:
Number of attachments: 5
Number of databases: 1
Quando a aplicação encerra, os valores acima são zerados.
Tá difícil de descobrir...
GOSTEI 0
Vinicius2k
29/09/2004
Este é um problema novo para mim... e, ao menos pelo que sei, se vc só estiver com a sua aplicação rodando no momento q pede as propriedades do FB Server, deveria constar 1 Attachment e 1 Database... ou no máximo 2 Attachments se vc estiver debugando por dentro do Delphi.
Honestamente, não sei o que pode ser... aparentemente, seu IBDatabase está replicado algumas vezes... se é que isto é possível.
O que eu posso lhe sugerir, e não tenho certeza se é a causa do problema é:
1. Atualize seu IBX (se eu não estiver enganado, vc já o fez):
http://codecentral.borland.com/codecentral/ccweb.exe/author?authorid=102
2. Certifique-se de q vc está usando uma versão estável do FB
1.0 -> 1.0.3.972
1.5 -> 1.5.0.4306
1.5.1 -> 1.5.1.4481
T+
Honestamente, não sei o que pode ser... aparentemente, seu IBDatabase está replicado algumas vezes... se é que isto é possível.
O que eu posso lhe sugerir, e não tenho certeza se é a causa do problema é:
1. Atualize seu IBX (se eu não estiver enganado, vc já o fez):
http://codecentral.borland.com/codecentral/ccweb.exe/author?authorid=102
2. Certifique-se de q vc está usando uma versão estável do FB
1.0 -> 1.0.3.972
1.5 -> 1.5.0.4306
1.5.1 -> 1.5.1.4481
T+
GOSTEI 0
Aerreira
29/09/2004
Honestamente, não sei o que pode ser... aparentemente, seu IBDatabase está replicado algumas vezes... se é que isto é possível.
1. Atualize seu IBX (se eu não estiver enganado, vc já o fez):
http://codecentral.borland.com/codecentral/ccweb.exe/author?authorid=102
Atualizei esta semana para IBX 5.04 D5-SP1
2. Certifique-se de q vc está usando uma versão estável do FB
1.0 -> 1.0.3.972
1.5 -> 1.5.0.4306
1.5.1 -> 1.5.1.4481
Acho que minha versão do Firebird é 1.0.0.796. Vou atualizar.
Mas acho que achei o problema. Eu estava usando IbTable direto (já sei que não deveria...) estarei migrando tudo para IBDataSet. Eu estou abrindo todas as tables (umas 25) no inicio da aplicação, acho que isso também não é bom.
Pergunto:
1) Convém abrir todos os datasets no inicio da aplicação ou é melhor abrir os datasets menos usados somente no momento em que forem necessários?
2) Relacionamentos master/detail são feitos apenas pelas PK e FK das tabelas ou é preciso definir os wheres dos selects ?
[]s
GOSTEI 0
Aerreira
29/09/2004
2. Certifique-se de q vc está usando uma versão estável do FB
1.0 -> 1.0.3.972
1.5 -> 1.5.0.4306
1.5.1 -> 1.5.1.4481
Atualizei o Firebird para 1.0.3 e o problema sumiu!!!
Ainda assim, preciso trocar as IBTables por IBDataSets mas estou tendo dificuldade para fazer os relacionamentos master/detail...
GOSTEI 0
Vinicius2k
29/09/2004
:D
Que bom q o problema se foi !
Sobre as suas perguntas...
1. Só abra o DataSet quando abrir o form ou executar a rotina onde ele será necessário... Abrir tudo compromete a performance da aplicação e, como vc estará trabalhando com dados em cache de memória, vc desperdiça uma chance de exibir os dados atualizados ao usuário. Quando fechar o form, feche o DataSet.
2. Eu sempre fiz master/details ´manuais´... no OnChangeData do DataSource Master eu fecho, passo a(s) chave(s) como parametro(s), e abro o Detail... Sinceramente, não sei lhe dizer se esta eh a melhor forma, mas sempre trabalhei assim, desde os tempos da BDE, pq sempre trabalhei com Queries, mesmo em bancos Desktop.
PKs e FKs são relacionamento no lado do servidor, e sua únicas funções são auxiliar na indexação e garantir a integridade referencial. O relacionamento no lado do cliente precisa ser feito por vc.
O colega afarias tem mais experiência com DataSets aninhados que seria a segunda forma se fazer o Master/Detail.
Anderson, quando ler este tópico, peço que oriente o colega com relação a aninhamentos no IBX... :wink:
T+
Que bom q o problema se foi !
Sobre as suas perguntas...
1. Só abra o DataSet quando abrir o form ou executar a rotina onde ele será necessário... Abrir tudo compromete a performance da aplicação e, como vc estará trabalhando com dados em cache de memória, vc desperdiça uma chance de exibir os dados atualizados ao usuário. Quando fechar o form, feche o DataSet.
2. Eu sempre fiz master/details ´manuais´... no OnChangeData do DataSource Master eu fecho, passo a(s) chave(s) como parametro(s), e abro o Detail... Sinceramente, não sei lhe dizer se esta eh a melhor forma, mas sempre trabalhei assim, desde os tempos da BDE, pq sempre trabalhei com Queries, mesmo em bancos Desktop.
PKs e FKs são relacionamento no lado do servidor, e sua únicas funções são auxiliar na indexação e garantir a integridade referencial. O relacionamento no lado do cliente precisa ser feito por vc.
O colega afarias tem mais experiência com DataSets aninhados que seria a segunda forma se fazer o Master/Detail.
Anderson, quando ler este tópico, peço que oriente o colega com relação a aninhamentos no IBX... :wink:
T+
GOSTEI 0
Aerreira
29/09/2004
2. Eu sempre fiz master/details ´manuais´... no OnChangeData do DataSource Master eu fecho, passo a(s) chave(s) como parametro(s), e abro o Detail...
Ok, suas explicações estão sendo muito valiosas, obrigado. Agora eu acho que o esquema que me passou acima talvez fique meio lento em alguns casos, por exemplo: tenho neste sistema um relacionamento Proprietários / Imóveis / Contratos e quando navego pelos proprietários os imóveis e contratos respectivos também são atualizados na mesma tela. Idem para navegação nos imóveis que faz atualização do detail contratos. Será que ficar abrindo, mudando parâmetros e fechando em cada registro que o usuário visualizar não vai ficar muito lento não?
O colega afarias tem mais experiência com DataSets aninhados que seria a segunda forma se fazer o Master/Detail.
Anderson, quando ler este tópico, peço que oriente o colega com relação a aninhamentos no IBX... :wink:
Acho que talvez essa forma de Nested Datasets possa ser uma solução mais rápida para este meu caso... AFarias, poderia me exclarecer o aninhamento de datasets melhor, pois o que lí no forum sobre o assunto ainda não foi suficiente para que eu compreenda como implementar.
Grato a todos,
GOSTEI 0
Afarias
29/09/2004
|Será que ficar abrindo, mudando parâmetros e fechando em cada
|registro que o usuário visualizar não vai ficar muito lento não?
Com as devidas chaves extrangeiras (ou índices) criadas geralmente q não. Esta solução é perfeita. Mas, para evitar fazer código vc pode apenas usar a forma ´padrão´ do Delphi:
Coloque um datasource ´ligado´ ao DataSet (IBDataSet ou IBQuery) mestre. No dataset ´detalhe´ coloque um SQL na forma::
select * from tabelatal where campo_chave_est = :campo_chave_prim
onde o parâmentro ´campo_chave_prim´ tem o mesmo nome do ´campo chave primária´ na tabela ´mestre´, então ´ligue´ a propriedade DataSource deste dataset ´detalhe´ ou datasource que falamos anteriormente (da tabela mestre)
pronto, ao navegar pela mestre, os registros do DataSet detalhe serão automáticamente ´filtrados´ (o SELECT será re-executado)
|Acho que talvez essa forma de Nested Datasets possa ser uma solução
|mais rápida para este meu caso...
Nested DataSets realizam a completa busca de todos os registros detalhes para cada meste para memória. Em muitos casos isso é MENOS eficiente q a solução mais simples discutida anteriormente (principalmente em aplicações em uma rede local e q precisa carregar muitos mestres)
Além do mais, exige o uso de MIDAS (ClientDataSets e DataSetProviders) os quais, se vc não está usando, vai exigir um certo estudo de sua parte nesses componentes.
Se realmente decidir partir para uma solução assim, post outros tópicos perguntando sobre o assunto (ou leia os já existentes no fórum)
T+
|registro que o usuário visualizar não vai ficar muito lento não?
Com as devidas chaves extrangeiras (ou índices) criadas geralmente q não. Esta solução é perfeita. Mas, para evitar fazer código vc pode apenas usar a forma ´padrão´ do Delphi:
Coloque um datasource ´ligado´ ao DataSet (IBDataSet ou IBQuery) mestre. No dataset ´detalhe´ coloque um SQL na forma::
select * from tabelatal where campo_chave_est = :campo_chave_prim
onde o parâmentro ´campo_chave_prim´ tem o mesmo nome do ´campo chave primária´ na tabela ´mestre´, então ´ligue´ a propriedade DataSource deste dataset ´detalhe´ ou datasource que falamos anteriormente (da tabela mestre)
pronto, ao navegar pela mestre, os registros do DataSet detalhe serão automáticamente ´filtrados´ (o SELECT será re-executado)
|Acho que talvez essa forma de Nested Datasets possa ser uma solução
|mais rápida para este meu caso...
Nested DataSets realizam a completa busca de todos os registros detalhes para cada meste para memória. Em muitos casos isso é MENOS eficiente q a solução mais simples discutida anteriormente (principalmente em aplicações em uma rede local e q precisa carregar muitos mestres)
Além do mais, exige o uso de MIDAS (ClientDataSets e DataSetProviders) os quais, se vc não está usando, vai exigir um certo estudo de sua parte nesses componentes.
Se realmente decidir partir para uma solução assim, post outros tópicos perguntando sobre o assunto (ou leia os já existentes no fórum)
T+
GOSTEI 0
Aerreira
29/09/2004
Com as devidas chaves extrangeiras (ou índices) criadas geralmente q não. Esta solução é perfeita. Mas, para evitar fazer código vc pode apenas usar a forma ´padrão´ do Delphi:
Funcionou perfeitamente fazendo a ligação da propriedade datasource do DataSet-Detalhe ao componente DataSource do DataSet Master. Fiz o relacionamento entre três tabelas (proprietários / imóveis / contratos) e funcionou perfeitamente e não ficou lento.
Agora compreendi melhor. A propriedade datasource do IBDataSet é o equivalente ao Mastersource do TTable ou IBTable, certo?
Nested DataSets realizam a completa busca de todos os registros detalhes para cada meste para memória. Em muitos casos isso é MENOS eficiente q a solução mais simples discutida anteriormente (principalmente em aplicações em uma rede local e q precisa carregar muitos mestres). Além do mais, exige o uso de MIDAS (ClientDataSets e DataSetProviders) os quais, se vc não está usando, vai exigir um certo estudo de sua parte nesses componentes.
Ok, já desisti dos Datasets aninhados...
Valeu amigos, acho que agora já posso andar com minhas pernas por um tempo... Qualquer coisa posto aqui no forum...
GOSTEI 0
Afarias
29/09/2004
|Agora compreendi melhor. A propriedade datasource do IBDataSet é o
|equivalente ao Mastersource do TTable ou IBTable, certo?
Certo!
T+
|equivalente ao Mastersource do TTable ou IBTable, certo?
Certo!
T+
GOSTEI 0
Mordred
29/09/2004
Notei que as telas em que uso master-detail estão ficando bastante lentas.
Uso os componentes da paleta Interbase e minha tabela já possui um índice de chave primária e dois índices de chaves estrangeiras. É necessário criar mais algum índice além desses índices automáticos?
O que posso estar fazendo de errado e como posso corrigir esse erro terrível? Alguém tem alguma sugestão?
Uso os componentes da paleta Interbase e minha tabela já possui um índice de chave primária e dois índices de chaves estrangeiras. É necessário criar mais algum índice além desses índices automáticos?
O que posso estar fazendo de errado e como posso corrigir esse erro terrível? Alguém tem alguma sugestão?
GOSTEI 0