Em um dos meus clientes é muito comum o desenvolvimento de aplicações Java voltadas para o ambiente desktop, aonde não raro enfrento problemas sérios de performance e consumo de recursos. O objetivo deste post é expor como usando o recurso de serialização de objetos oferecido pela plataforma Java consegui resolver (ou ao menos minimizar ao extremo) este desafio.
Imagine a seguinte situação: sua aplicação desktop acessa informações presentes em um banco de dados relacional. Dado que você precisa de produtividade, opta por usar uma ferramenta ORM como Hibernate ou JPA. Não resta dúvidas de que trata-se de um recurso maravilhoso, mas infelizmente traz consigo um custo de memória (precisamos carregar o motor de mapeamento objeto relacional, além disto, muitas vezes usamos cacheamento que, ao menos em parte, fica em memória) e performance (trata-se de mais uma camada no sistema). Em algumas situações causa um aumento no tempo de carregamento dos nossos sistemas tão grande que, não raro, você se vê questionando o ganho real do seu uso.
Imagine agora outra situação: sua aplicação trabalha apenas com JDBC e, com isto, sua performance é superior à obtida usando JPA ou Hibernate (apesar de sua existência neste caso ser mais infeliz), porém há limitações no número de conexões que podem ser feitas ao SGBD e, pior ainda, o tempo gasto estabelecendo a conexão com o SGBD é alto. Em situações como esta, o tal “ganho de performance” por não se estar usando Hibernate se perde totalmente, pois você nem tem o cacheamento automático provido pelo ORM.
Em ambos os casos, como resolver o problema? Simples: evitando ao máximo que seja necessário estabelecer QUALQUER tipo de conexão com o servidor.
Entra em cena a serialização de objetos
Todo sistema possui informações cuja alteração seja rara, ou seja, registros que apenas são inseridos no banco de dados e em raras situações tenham seus dados alterados. Como exemplos posso citar um cadastro de fornecedores ou endereços. Tratam-se de informações que são usadas, em 90% dos casos, apenas para consulta ou na composição de tipos mais complexos. Pergunte-se: é realmente necessário sempre pedir ao SGBD estes dados?
Nestes casos, a serialização de objetos cai como uma luva. E se você está em um ambiente corporativo, é possível inclusive fazer com que um único usuário beneficie todos os demais com um custo adicional mínimo. Vou ilustrar a situação usando como exemplo uma aplicação desktop que precise expor em um formulário uma caixa de seleção contendo a listagem de fornecedores presentes no banco de dados.
Vamos supor que esta nossa aplicação use o Hibernate. Neste caso, ao criar uma nova instância do formulário, precisamos obter a listagem de fornecedores seguindo o seguinte procedimento:
- É criada uma consulta no Hibernate usando criteria ou HQL
- Esta consulta é transformada em comandos SQL que serão enviados ao driver JDBC
- O driver JDBC envia a consulta para o SGBD
- O SGBD executa a consulta e retorna o resultado para o cliente
- O driver JDBC traduz o resultado enviado pelo SGBD para um objeto java.sql.Recordset
- O Hibernate cria novas instâncias da classe Fornecedor e, via reflexão, preenche todos os seus atributos
- E, finalmente, é retornada uma lista contendo o resultado para o cliente
Se esta for a primeira consulta feita pela aplicação, o seu usuário ainda vai ter de sofrer um pouquinho com o carregamento do SessionFactory do Hibernate.
Agora, quer ver como as coisas ficam mais simples usando serialização? Suponha que eu já tenha serializado esta lista de fornecedores em um arquivo presente em minha rede. O seguinte procedimento seria adotado.
- É verificado se o arquivo existe na rede.
- Se o arquivo existe, então este é desserializado em uma lista de fornecedores e retornado ao cliente.
- Se o arquivo não existe, execute o longo procedimento exposto acima novamente, com a diferença de que, agora, você serializará o resultado em arquivo no final.
Observe que interessante: não precisei carregar o Hibernate nem comunicar-me com qualquer servidor. Claro, se o arquivo não existisse, todo o processo citado acima seria necessário, porém em um ambiente de rede, só precisaria ser feito uma vez pelo primeiro usuário que necessitasse da lista de fornecedores. Dai pra frente, todos os demais usuários obteriam o ganho de performance que apresentei.
Mas o que é serialização de objetos
Ok, talvez você esteja apenas começando a aprender Java e não saiba o que é esta tal de serialização. Porcamente falando, serialização é o processo de salvar em arquivo um objeto presente na memória do seu computador.
Se eu quisesse salvar a minha listagem de fornecedores em um arquivo, o código abaixo daria conta do recado:
java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(new FileOutputStream(new File("fornecedores"))); oos.writeObject(listaFornecedores); oos.close();
E, para transformar o meu arquivo em objeto, de novo apenas três linhas fariam o trabalho pra mim.
java.io.ObjectInputStream ois = new java.io.ObjectInputStream(new FileInputStream(new File("fornecedores"))); List<Fornecedor> lista = (List<Fornecedor>) ois.readObject(); ois.close();
Detalhe: só podem ser serializados objetos que implementem a interface java.io.Serializable.
Omiti as excessões apenas para expor como é um recurso absurdamente fácil de ser usado.
Armadilhas a serem evitadas
O principal desafio desta abordagem é manter o cache sempre atualizado. Tenho duas soluções para este problema. A mais simples é de tempos em tempos apagar os arquivos de cache da rede. A mais complexa consiste em, toda vez que for persistir uma novo registro no banco de dados, apagar os arquivos de cache.
Dica: evite ao máximo chamar a função exist() da classe java.io.File, pois esta é absurdamente cara, visto que a cada chamada acessa o gerenciador de segurança do Java. Dado que o objetivo de qualquer sistema é expor os dados para o usuário, você pode sempre, ao verificar a existência do cache, escrever código similar ao exposto abaixo:
private List<Fornecedor> getListaCache() { try { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("fornecedores"))); List<Fornecedor> resultado = (List<Fornecedor>) ois.readObject(); ois.close(); return resultado; } catch (Throwable t) { return null; } } public List<Fornecedor> getFornecedores() { List<Fornecedor> no_cache = getListaCache(); if (no_cache != null) return no_cache; // caso contrário, procedimento padrão, serializando o resultado no final }
Outra armadilha: em um ambiente de rede, evite serializar os dados no HD local do usuário. Sempre que possível, opte por usar um drive de rede. Assim, caso seja necessário uma atualização do cache imediata, você, como administrador do sistema, em último caso sempre poderá apagar o arquivo de cache, forçando o cliente a recriá-lo novamente.
Fique atento também ao que será serializado. Dados que apenas ocasionalmente são consultados não são um bom alvo. Opte apenas por aquelas informações que são vitais ao uso do seu sistema e cuja atualização seja rara.
E, a principal armadilha: JAMAIS use esta técnica em entidades que precisem ser constantemente atualizadas na base de dados.
Padrão: buscando um único registro
Há situações em que não é necessário buscar uma lista de registros, mas apenas um, o que normalmente é feito executando uma consulta por chave primária. Nestes casos, adotei um padrão bastante simples. Crio um diretório na rede chamado cache e, dentro dele, um subdiretório que identifique o tipo da minha entidade. No caso de fornecedores, chamo este diretório, por exemplo, de /cache/fornecedor. No interior deste diretório armazeno arquivos cujo nome corresponda à chave primária da entidade que desejo buscar no banco de dados.
Mas se o Hibernate já possui sistema de cache, pra que usar serialização?
Como diriam os candidatos a presidente em um debate… esta é uma pergunta importantíssima.
Simples: porque a serialização, tal como estou expondo neste post, deve ser usada ANTES da primeira chamada ao Hibernate, pois assim, em algumas situações, consegue-se evitar o carregamento deste framework e, consequentemente, nosso usuário final terá um sistema muito mais leve e responsível.
Se sua aplicação vai ser executada em um servidor nem sei se o uso desta técnica trará algum resultado que realmente valha à pena.
Conclusões
Uso esta técnica para resolver os problemas de performance que enfrento em aplicações desktop, aonde normalmente os recursos computacionais podem ser mais limitados (as malditas “máquinas brancas”). O que pude observar é que, nestes casos, obtenho ganhos de performance astronômicos, pois a comunicação com o SGBD é reduzida a apenas o estritamente necessário.
Outro ganho que obtenho é o tempo de inicialização da aplicação, pois é muito comum neste momento ser necessária a execução de alguma consulta no SGBD. Sendo assim, esta é uma técnica que, ao menos por enquanto, cai como uma luva quando aplicada ao ambiente desktop.
Aos que queiram se aprofundar mais no assunto, sugiro a leitura deste post: “The Java serialization algorithm revealed”, que explica com detalhes o processo de serialização: http://www.javaworld.com/community/node/2915
Agora: sabem o que me choca nesta história toda? Este recurso maravilhoso oferecido pela plataforma é raríssimas vezes usado pelos desenvolvedores. Da pra acreditar???
Minha dúvida, sempre que se fala em serialização, é a seguinte. Como você lida com a evolução da classe no sistema? O formato do arquivo serializado é, geralmente, totalmente dependente dos campos da classe.
Você até pode alterar o SerialVersionUID, mas logo, estará com dezenas de serializadores e desserializadores na sua própria classe.
Uma opção, que me parece simples e alinhada com a solução que você propôs, seria testar o SerialVersionUID e desprezar o arquivo caso o cache não bata com a versão da classe. Aí sim, recorre-se mais uma vez ao Hibernate. Seria por aí?
Yeap, este é um problema sério, e por esta razão as pessoas não usam serialização para salvar dados como formato padrão.
Neste caso, o objetivo é evitar ao máximo possível o acesso ao SGBD ou o carregamento do Hibernate. Sendo assim, os dados serializados são vistos como descartáveis (se der problema no carregamento o máximo que ocorre é a perda da performance ganha).
Internamente, por exemplo, se ocorre algum erro durante a desserialização e topo com um ClassCastException, o que faço é simplesmente apagar o arquivo da rede e em seguida gerá-lo novamente, assim o arquivo serializado estará atualizado com a versão atual da classe.
Até chegar a esta técnica, também tentei outras alterantivas, como por exemplo serialização em XML. Neste caso, o problema da evolução das classes nem ocorreria, pois eu teria um padrão bem montado. O problema é que nesta situação o objetivo é performance, e a serialização binária tirava o XML da jogada (ordens de magnitude mais eficiente).
Resumindo: neste caso, o problema da evolução das classes não se aplica. Mas pensando em um ambiente em que os dados serializados seriam usados como formato de armazenamento, eu optaria por XML.
Oi pessoal,
É exatamente para isso que serve o atributo serialVersionUID das classes que podem ser serializadas!
Tem um post muito bom no blog da caelum que explica isso: http://blog.caelum.com.br/2008/04/01/entendendo-o-serialversionuid/
[]s,
Opa Lucas!
Este post é do caralho. Lembro de ter topado com ele a algum tempo atrás. O problema é que mesmo assim a gente continua com o mesmo problema, quando, por exemplo, são removidos ou adicionados atributos na classe.
No final das contas, o que percebo é o seguinte: serialização só mesmo pra situações em que os dados são temporários, como cache, comunicação em rede, etc.
Sabe um negócio que estou estudando a possibilidade de uso? Prevayler. Mas ainda estou nos primeiros passos ainda.
Assim que tiver uma experiência melhor com ele, prometo postar aqui!
Grande abraço!
Kiko,
Onde trabalho, usamos aplicações cliente servidor. Tem lá o cliente swing que faz requisições pra um servidor de aplicação. Você mesmo falou que não sabe se essa técnica vai fazer alguma diferença. Por que? Você acha que pelas consultas ao banco estarem dentro de um AS as coisas podem ser mais rápidas?
As vezes precisamos de um mesmo objeto várias vezes e, ao invés de buscarmos toda vez no banco, colocamos em algo que chamamos de contexto do cliente. Algo parecido com o context do JEE, mas no cliente. O contexto é algo bem simples, mas que corta uma bocado de caminho. Não serializamos porque ele vai ficar somente no cliente e, provavelmente, será diferente pra cada cliente. Podemos dizer que isso é cacheamento?
Aliás, ótimo texto!
Abraço.
Oi Andre,
na realidade, é exatamente NESTE caso, Cliente/Servidor em que apliquei a técnica. No caso, o que fiz foi armazenar os dados serializados em um diretório de rede, pois assim todos os clientes podem fazer a consulta lá primeiro ao invés de ter de ir ao SGBD.
Fico feliz que tenha gostado. Valeu!
A idéia e a justificativa apresentadas são boas, mas pense no custo de manter o “cache” (objetos serializados) sempre atualizados. E mais, imagine a situação de pesquisa por vários campos diferentes de uma tabelas nesse “cache”. Fazer consultas com “like” em qualquer campo de uma tabela são fáceis, mas e numa coleção recuperada de uma serialização? E se forem 10 tabelas nesse “cache”?
Repito que a idéia é boa, mas o EhCache oferece esse recurso de maneira bem mais robusta e transparente. Nele você pode configurar o cache para ser 100% em arquivos indexados em disco e não na memória principal. Assim, você continua usando suas HQLs e Criterias normalmente e ele se encarrega de manter atualizado e usar os arquivos indexados pra você. E esses arquivos também podem ficar numa pasta compartilhada na rede.
Talvez (só testando para comprovar) o EhCache seja um pouco mais lento que essa sua proposta “hard code”, mas será tão confiável quanto a solução consolidada do EhCache?
Lembro que um “select * from…” que temos na empresa retornava ~16k linhas. Sem EhCache ela levava em torno de 7 segundos. Com EhCache, menos de 0,5s. E o banco era remoto.
Opa, seu ponto é muito bom José.
Por isto que, lendo meu texto com um pouco mais de atenção, você deve prestar atenção em alguns pontos:
* Eu recomendo a técnica apenas a aqueles objetos que são pouquíssimas vezes editados (de preferência, nunca editados) e não a todos os dados ou consultas possíveis no banco de dados (isto seria burrice). Neste caso, o custo de manutenção do cache é baixíssimo: tudo o que você precisa fazer é apagar os arquivos de tempos em tempos caso necessário.
(consultas em que haja um like, por exemplo, não são bons candidatos para a aplicação da técnica, pois muitas vezes o conteúdo deste like varia demais e, consequentemente, não seria uma boa idéia)
* Um dos objetivos é justamente postergar ao máximo o carregamento de frameworks mais pesados, como Spring ou HIbernate. Em diversas situações, observei que meus usuários podiam usar o sistema por horas sem que fosse necessário carregá-los: consequentemente, o tempo de resposta dos usuários fica muito superior.
* Ehcache: cheguei a pensar em sua utilização também nesta técnica. Aliás, o ehcache já é usado por default pelo Hibernate. Neste caso que estou usando, no primeiro momento até o carergamento do Hibernate, ele se mostra mais como um problema do que uma solução, isto porque é uma dependência a mais pro seu sistema e, dado que o próprio Java já oferece a possibilidade de serialização, economizo assim um pouco mais e recursos para meus usuários (lembre-se: um dos meus objetivos aqui é economizar MEMÓRIA também).
Com relação à confiabilidade do Ehcache ou da serialização direta, na prática, é a mesma por uma razão bem simples: o programador que faz merda serializando diretamente também poderia fazer a mesma merda usando ehcache. Nestes casos, o problema fica realmente entre a cadeira e o teclado.
Outro ponto a ser lembrado aqui Yoshiriro, é que estou tratando do ambiente desktop. NO ambiente servidor, eu usaria o ehcache ao invés desta técnica, pois os meus recursos são bem maiores.
Opa, aproveitando ainda o gancho da sua pergunta Yoshiriro (ela é realmente muito boa!)
Outro ponto importante desta técnica é que um usuário, no ambiente de rede, beneficie a todos os outros ao serializar os objetos pela primeira vez.
Usando o ehcache (a não ser que você tenha o servidor ehcache instalado, o que aumenta o custo da aplicação), isto não é possível, pois cada usuário teria o seu próprio cacheamento. Deste modo, consigo basicamente o mesmo resultado (se bobear, superior), com a vantagem de usar apenas o básico oferecido pela plataforma.
Cara, eu adoro quando pintam comentários como o seu neste blog. Valeu!
Perdão, a consulta que citei retornava ~6k e não ~16k linhas. Depois que li vi que digitei errado ^^’
Não quis desmerecer sua solução, inclusive a elogiei. Eu mesmo implementei alguas coisas com serialização com sucesso. Apenas quis destacar que ela possui limitações quando o uso é para criar uma espécie de “cache” de objetos do banco. Mesmo que o cache fosse sobre 3 tabelas… vamos supor Bairro, Cidade e Estado. Não raro podem haver pesquisas com parte do nome de bairo, cidade e estado, não é? Ou seja, precisa-se do “like”. E pesquisa de todos os bairos de carta cidade? E pesquisa de bairro com população X de certo estado? Com EhCache, isso tudo fica transparente, já com Objetos serializados seria um grande trabalho de programação.
Quanto a atualização dos registros, mesmo que a frequencia de atualização seja muito baixa, o menor erro pode causar um prejuizo enorme. E como o EhCache é uma solução antiga e muito testada, as chances de algum problema são bem menores. Portanto não acredito que “o problema fica realmente entre a cadeira e o teclado”. Lembre que com EhCache o programador faz suas consultas exatamente como faria sem ele.
Insisto, mesmo que não podes afirmar catgoricamente que fazer esse tipo de “cache no braço” vai ser mais performático que um EhCache acessando arquivos indexados. Sem teste fica só no “eu tenho certeza
Oi Yoshiriro, temos um problema de comunicação aqui. Eu não acho que você desmereceu a solução, muito pelo contrário, acho que você a enriqueceu ao tratar de um ponto importante.
O problema com o ehcache, neste caso, aplicações desktop, é aquele que já lhe disse anteriormente: ele encarece a solução, pois além de eu estar adicionando mais arquivos jar como dependências, estou tendo o mesmo ganho com os arquivos serializados, entende? E no ambiente desktop, quanto menor for o meu número de dependências externas, melhor (neste ambiente, isto é crítico).
Com relação à performance ser mais rápida ou não usando ehcache ou arquivos serializados José, eu vou ter o seguinte problema com o ehcache: eu vou ter de carregá-lo. Lembra que no post, um dos meus objetivos é justamente prover aos meus usuários um startup superior da aplicação?
Se for para fazer consultas nos arquivos serializados, novamente, não recomendaria esta técnica. Observe que no post eu só trato de duas situações.
* Aquela em que eu preciso de todos os registros de determinado tipo (e estes são do tipo que não sofrem alterações (exemplo: listagem de cidades e estados))
* Um registro específico, quando a busca é por chave primária.
Nestas duas situações, nem há o que discutir com relação à performance: a serialização será mais rápida, pois eu não preciso carregar nenhum motor de cacehamento, como o ehcache. Além disto, levando em consideração que o acesso é direto ao arquivo, e eu também não tenho uma camada a mais entre minha aplicação e os dados, a performance será superior.
Por esta razão eu nem sequer menciono a possibilidade de usar esta técnica para fazer consultas mais avançadas, como as que você expõe no seu comentário.
… perdão, enviei sem querer… continuando ^^’
(…) Sem teste fica só no “eu tenho certeza que é mais rápido”.
Veja, não sei qual seu nivel de conhecimento sobre o EhCache, mas vou descrevê-lo um pouco aqui para ajudar os eventuais “espectadores” desse debate técnico.
Como disse antes, ele pode ser confiurado para usar arquivos indexados em disco e não memória principal, podendo beneficiar sim aplicações desktop, se esses arquivos estiverem numa pasta compartilhada na rede. E mais: como o EhCache funciona de maneira transparente, caso a comunicação com essa pasta “caia”, ele simplesmente vai no banco de dados mesmo. O programador fica despreocupado em tratar isso.
Ele armazena os resultados associando à query enviada. Assim, ele vai construindo o cache na medida que as consultas vão sendo enviadas. Logo, num primeiro momento, ele com certeza será mais lento que uma solução “hard code” de serialização, mas conforme os usuários vão usando, o cache vai ficado mais completo, deixando as consultas cada vez mais rápidas.
Exemplo (ainda imaginando cache das tabelas Bairro, Cidade e Estado):
– Um usuário faz uma consulta pedindo todos os bairros com menos de 2000 habitantes duma certa cidade de um certo estado.
-> A consulta retorna 100 registros e leva 2 segundos para retornar ao cliente.
– Certo tempo depois os dados dessas tabelas não sofreram mudanças logo, o EhCache mantém os mesmos arquivos indexados.
– Então o usuário faz a mesma consulta: resultado em menos de 0,3 segundos trazendo apenas 100 objetos pela rede.
– No caso de serialização, a não ser que se tenha um BAITA de um trabalho de programação, a solução de serialização sempre traria pela rede todos as dezenas de milhares de registros de bairros, cidades e estados, não é?
Usando serialização, se uma tabela retorna 1000 linhas, sua deserialização sempre trará uma coleção de 1000 objetos pela rede. Com EhCache, se a consulta retorna 100 linhas, 100 linhas trará pela rede. Se forem 10 linhas, 10 linhas trará.
Enfim, queria apenas apresentar aos leitores do seu ótimo blog os pontos negativos de sua abordagem e apresentar a opção do EhCache usando arquivos indexados em disco.
Os leitores vão avaliar quando será melhor usar sua abordagem (válida, usada por mim mesmo como já disse) ou o EhCache.
[]s.
Oi Yoshiriro,
eu uso bastante o ehcache, mas não neste caso que mencionei, pela razão que expus no meu último comentário: eu tenho de carregá-lo. :)
Um dos meus objetivos é diminuir o startup e o número de dependências dos projetos. Com relação à performance, eu posso te dizer que nas duas situações que expus a performance da serialização direta é melhor porque eu já fiz o teste. :)
Aliás, não só com o Ehcache. Eu usei também o Memcached (escrevi sobre isto aqui: https://devkico.itexto.com.br/?p=692). E para as situações do tipo
a) traga pra mim todos os registros
b) traga pra mim apenas um registro com base na chave primária
a serialização direta é muito mais performática justamente pelo fato do acesso, ao contrário do que rola com um motor de cache ser direto: eu não preciso carregar um componente a mais e somente depois obter os dados caso existam. Eu simplesmente tento acessar o arquivo diretamente e, em caso de sucesso, retorno o conteúdo.
Agora, pra consultas que fujam das duas situações, concordo 100% com você.
Grande abraço! :)
Vejo que isso poderia ser útil em um cadastro de clientes, que carrega uma lista de cidades (que por sinal, não deveria mudar nunca (ou muuuito raramente))…
bom post :)
Este é um caso ideal para a técnica Carlos.
Valeu!
Putz muito louco o POST, até há minutos atrás tinha muitas dúvidas sobre o uso da serialização, diminuiu bastante! Parabéns Kico. :)
Apenas quero entender melhor, o que foi proposto aqui; Assim, pretendo testar a performance sem e com a serialização. Criando um banco com as 3 tabelas,ex: bairro, cidade , estado. MySQL mesmo ou OracleXP? Sugestão?
Usando uma cópia antiga da base da ECT, comprada em CD para um cliente, poderia usar o seguinte , exemplo de historia do usuário: O cliente ao informar o cep , submete pedido para recuperar os seguintes dados: cidade, estado e bairro. Neste caso seria interessante usar serialização ou o ehcache? E se não for pedir demais, um exemplo do código.
Penso +- assim:
três Beans – cidade, bairro, estado – implements java.io.Serializable na declaração da classe.
depois criação do atributo public static final long serialVersionUID = 1L;
construtores de campo e classe, o getters e os setters, equals e hashcode.
Criação do HibernateUtil, completinho bacana. Os famosos DAOGenericos(HQL e Criteria) e para facilitar uso de algum controller sem spring por enquanto.
2 view: Uma modelo jsf(*.faces) e outra Swing. Se for usando tomcat, poderia rodar localhost para simular tudo que foi proposto, aqui.
Lógico que não espero os arquivos.jar desse projetinho , apenas um exclarecimento em que momento devo colocar em ação os seus exemplos de output e input e como devo fazer para poder perceber a performance, tipo um System. …. timeMilisenconds?
Acredito que todos ficaríamos muitíssimos satisfeitos e agradecidos pela sua ajuda social!!!
Mais uma vez parabéns pela iniciativa e clareza de pensamento.
Oi Christian, esta sua linha de raciocínio funcionaria legal sim.
O ganho de perforamance, você deve se lembrar, vai ser proveniente de você não estar fazendo acessos remotos ao servidor de SGBD e execução deste, que é cara.
Lembre-se do seguinte: os dados serializados não devem JAMAIS ser pensados como algo a longo prazo ok? Isto porque suas classes podem mudar, removendo ou adicionando atributos, ou mesmo desatualização das informações com relação á fonte original ok?
Com relação a qual BD, bem: não vai fazer tanta diferença assim, pois o padrão a ser aplicado é exatamente o mesmo (só vai mudar a “marca” do seu SGBD :) ).
Fico feliz que tenha gostado Christian, valeu!
Olá!
Estou fazendo um trabalho para Faculdade e estou com um problema que acho que você terá domínio para me ajudar a esclarecer…
Ocorre o seguinte:
Tenho duas aplicações (1 Desktop e 1 WEB):
A aplicação Desktop terá uma função de Servidor onde ficará colhendo pela porta Serial da máquina dados de um Hardware que aciona alguns dispositivos (Lâmpadas, Motores, Sensores, etc) e salvará no BD o Status de cada componente. Esta rotina se repete constantemente a cada 0,5 segundos.
A aplicação WEB tem a função de “LER” cada Status no BD e apresentar de forma “Gráfica” em uma página WEB cada Status de todos os dispositivos (Conteito de Sistemas Supervisórios).
Problema: A disputa por gravação/leitura do banco será extremamente grande devido ao tempo de “Refresh” dos Status de cada dispositivo. Minha preocupação neste caso é o tempo de resposta.
Solução adotada (Temporariamente):
A aplicação Desktop ao mesmo tempo que salva os dados no BD cria um arquivo .TXT com o último Status lido (dessa forma não precisa salvar toda a tabela em .TXT).
A aplicação WEB faz a leitura deste arquivo e não do BD.
PROBLEMA 2: Eu fiquei em dúvida se ocorrer em algum momento em que a aplicação Desktop estiver “Salvando” o arquivo .TXT e a aplicação WEB estiver tentando “Ler” o mesmo arquivo, poderá ocorrer alguma falha na gravação ou leitura do arquivo??
Outra dúvida: O acesso ao arquivo .TXT seria mais rápido do que direto ao BD?
E por fim: Se eu fizer a consulta do sistema WEB diretamente no BD o SGBD se vira pra não ocorrer conflitos na disputa pelo BD? Mas o tempo de resposta poderia ser alto, certo?
Parabéns pelo POST… quando eu resolvi salvar em arquivo .TXT eu nem sabia que isto poderia se chamar serialização… rs
Muito obrigado,
Herivelton
Oi Herivelton,
fico feliz que tenha gostado. Valeu.
normalmente, o acesso a arquivos locais é muito mais rápido que a um servidor, pois são menos camadas de acesso (você não está fazendo conexões de rede, autenticando, etc).
No entanto, depende: em um arquivo texto gigantesco, talvez o acesso a um BD seja mais rápido, pois você possui recursos como indexação. Cada caso é único, então teria de analisar com mais detalhes.
Se uma aplicação está escrevendo em um arquivo, enquanto outra está lendo ao mesmo tempo, você pode sim, enfrentar alguns problemas. Normalmente, a aplicação que tentar escrever será barrada pois o arquivo estará em uso por outro processo OU, o que é pior: o leitor pode ficar lendo o arquivo indefinidamente (é uma race condition).
O ideal é que haja uma fachada para acessar este recurso.
Olá, boa noite!
Criei todo o controle via BD mesmo. Criei alguns Triggers e Procedures que fazem o gerenciamento dos dados sem que eu tenha que me preocupar em fazer um controle paralelo.
Tanto a leitura quanto gravação ficaram com tempos de acesso e respostas perfeitamente aceitáveis.
Muito obrigado,
Herivelton.
Pingback: Java: como a serialização de objetos pode salvar sua aplicação desktop « Spigando e Aprendendo