Primeiro de tudo, obrigado pelas respostas. Vou tentar trabalhar um pouco sobre suas respostas mesmo para tentar explicar meu ponto de vista.
Compreendo que pela clareza do código, pelo que aprendemos “nos livros”, etc… Mas me refiro em questão de performance.
Estou estudando mais é “formas de aumentar a performance”, pois é isso que vai fazer a diferença para o cliente.
[quote]agora, uma pergunta, se vc tiver um objeto que tem a primary key setada… não quer dizer que quando vc for ao banco, vc já pode considerar que será para um update? [/quote]Vou te explicar como costumo escrever um código que use isso (depende muito do contexto, normalmente busco criar um objeto já persistindo em disco):
Eu tenho uma aplicação web em que eu cadastro um usuário, por exemplo, mas é possível, durante o cadastro, o usuário postar uma foto. Nesse caso, eu crio um registro temporário, com uma descrição temporária, no momento que ele clica no “novo usuário”, para que quando upar a foto, tenha um registro para a FK fazer referência.
Quando ele grava, eu altero os dados necessários com um update, até aí tudo bem. Mas acontece que um usuário pode desistir do cadastro no meio do processo (e nesse caso, nem sempre sabemos que ele desistiu, portanto não podemos apagar o registro). E quando o mesmo usuário vai cadastrar outro usuário, caso antes tenha desistido, ao invés de criar um novo registro, ele busca o antigo e updateia.
Tá, esse exemplo do usuário eu nunca usei, mas não é incomum situações como essa, que preciso colocar um insert/update no mesmo método, dependendo deles.
[quote]Não é recomentado fazer um cache do banco na “mão”, tem frameworks para isto.
porque não/criar um cache: vc teria que implementar todo o controle de transação na mão, e garantir a integridade do cache, só em falar em “implementar uma cache” já teria um certo problema, pq é recomentado vc usar caches já prontas, que tenham todo uma infra já feita… [/quote]
Acontece que eu já dei uma olhada nos frameworks para cache, e nenhum que eu encontrei atendeu essa minha necessidade específica ou acabava sendo mais demorado implementar ele que criar esse HashMap.
Veja bem, eu quero, por exemplo, listar os 10 últimos registros inseridos numa determinada tabela, mas tenho umas 40000 requisições por minuto, não encontrei nenhuma solução melhor que fazer isso (visto que não são muitas queries, apenas umas 10 estáticas diferentes, e as informações não são necessariamente inseridas por essa aplicação java)
Se fosse algum outro caso, vi que um EntidadManager soluciona muito bem essa questão de cache.
Na verdade nem é tanto alta performance, é que estou estudando mesmo algumas formas de otimizar o desempenho de páginas web. No caso, eu vi que os sites de notícas (em PHP e ASP) serializam os objetos para XML para poder melhorar essa questão de acesso ao banco (no caso, eles esperam cerca de 40000 requisições por minuto). Mas tenho mesmo é experiência com banco de dados de BI, e uma tabela de uns 100.000.000 de registros acaba sendo bem lento para fazer uma consulta de uma linha… Por isso acabo sendo “crítico demais” com desempenho de aplicações menores. (heheh, principalmente por estar acostumado a otimizar consultas… Já fiz consultas de 5 horas cair para 10 minutos)
Ps: Lendo o link que vc me mandou, parece que o EntityManager tem mais funcionalidades que eu pensava. Mas achei ele meio que um “exagero” para esse caso que expliquei. Conhece algum método de uso dele ou algum framework que faça algo mais próximo do que eu expliquei?
[quote]Seguinte, esta estoria de pools, não é mais necessário “implementar” um do zero, todos os containers, applications servers que conheco tem um embutido… desta forma tme um cara que gerencia para vc o estas paradas… e sim, geralmente é legal vc configurar o pool para que ele tenha mais de uma conexão aberta… desta forma seu sistema não fica threadsafe em relação ao banco. [/quote]Legal, dei uma procurada sobre pool de conexões TOMCAT, e achei algumas coisas interessantes. Mas sabe me dizer se o que eu implemento, para o tomcat, por exemplo (sobre o pool de conexões) vai funcionar no glassfish, jboss, etc…?
Desculpe as perguntas serem “idiotas”, mas é que eu sou meio “fissurado” em melhorar performance e busco fazer o mais intuitivo possível. (tá, nem sempre consigo, mas é errando que se aprende)
EDIT: heheh, enquanto respondia (fazendo outras coisas, acabei demorando muito para responder) foram aparecendo novas respostas, vou atualizar esse post.
Acredito que um controle de transação seria mais custoso ao banco e o lock na tabela para leitura poderia permitir uma inserção de algum registro dependendo do banco não? Pelo que sei, alguns bancos travam as linhas retornadas do select, e não a tabela inteira, se não houve linhas retornadas não trava nada na tabela.
E se não é garantir a unicidade dos registros, qual a função de uma chave primária? Na maioria dos bancos ela é um índice UNIQUE, estruturado e clusterizado para reduzir o tempo de pesquisa por eles e garantir a unicidade. E sempre vi nas documentações dos SGBDs MySQL e Oracle (que possuem REPLACE INTO e MERGE INTO) que essa é a função do replace into e merge into, testar a inserção na chave primária para atualizar ou inserir o registro.
Mas concordo que para o que vem na camada da aplicação (no caso, JAVA), tem uma perda muito grande de desempenho por causa do pipeline dos processadores.
Vejam bem, não é raro eu inserir no banco uns arquivos de texto de uns 4GB ou mais (no geral uso o Kettle para isso, mas em casos isolados tenho que escrever uma rotina para corrigir os erros do arquivo, como datas com vários formatos, etc…) E já houve casos em que eu tive que inserir/atualizar um registro (vinha várias versões do mesmo registro em arquivos diferentes, como carregava da menor data para a maior, ficava sempre com o registro mais recente).
Foi aí que eu percebi que o Try/Catch fica mais rápido que o Update->insert (mas considere que é porque 80% era somente insert’s)
No mesmo caso, percebi que o replace into, no caso do mysql ficava mais lento que somente inserts em cerca de 20% do tempo. Não cheguei a testar no Oracle o Merge Into, porque mudei a minha forma de fazer esse processo inserindo tudo em uma tabela temporária antes (o que consome muito tempspace, mas é mais rápido principalmente quando temos que atualizar várias tabelas com a mesma informação)
Agora, baseado no desenvolvimento WEB, melhor mesmo abrir uma transação? não ficaria mais lento o ambiente em geral? tanto banco quanto servidor?