Usando hiberante de forma otimizada

428 visualizações

Publicada em

Usado Hibernate de forma otimizada

Publicada em: Software
0 comentários
0 gostaram
Estatísticas
Notas
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

Sem downloads
Visualizações
Visualizações totais
428
No SlideShare
0
A partir de incorporações
0
Número de incorporações
2
Ações
Compartilhamentos
0
Downloads
7
Comentários
0
Gostaram
0
Incorporações 0
Nenhuma incorporação

Nenhuma nota no slide

Usando hiberante de forma otimizada

  1. 1. S Usando Hibernate de Forma Otimizada Jadson Santos
  2. 2. Hibernate Otimizado S  Hibernate S  O Hibernate é um framework para o mapeamento objeto- relacional escrito na linguagem Java. Este framework facilita o mapeamento dos atributos entre uma base tradicional de dados relacionais e o modelo objeto de uma aplicação, mediante o uso de arquivos XML ou anotações Java.
  3. 3. Hibernate Otimizado S  A principal promessa do Hibernate S  Quando a gente começa a estudar o Hibernate, a principal promessa para vender o produto é: O Hibernate gera as chamadas SQL e libera o desenvolvedor de trabalhar com os dados de forma relacional, desde que os mapeamentos das classes de domínio tenham sido realizados, o desenvolvedor irá trabalhar apenas com objetos S  Então oba S  Eu tenho o id da entidade e para recuperar seus dados eu vou no meu Dao que usa Hibernate e faço: Entidade e = dao.findById(1); S  E tenho o objeto “e” populado, simples!
  4. 4. Hibernate Otimizado S  O problema é que essa promessa não é cumprida S  Na prática, apenas se for uma entidade de domínio com poucos dados e sem relacionamento com outras entidades do sistema isso vai funcionar public class TipoAluno{ @Id private int id; @Column(name = "descricao") private String descricao; }
  5. 5. Hibernate Otimizado S  Normalmente no seu sistema você terá apenas 10 ou 20 tipos de alunos e serão sempre recuperados apenas o id e a descrição S  Para entidades que possuem dezenas de milhares de linhas na tabela para cima, e que possuam muitos relacionamentos essa abordagem deixar o seu sistema lendo e não escalável.
  6. 6. Hibernate Otimizado public class Aluno{ @ManyToOne @JoinColumn(name = "id_tipo_aluno") private TipoAluno tipo; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name ="id_discipina”) private Disciplina discipinas; }
  7. 7. Hibernate Otimizado S  O que vai ocorrer se você for usar “orientação a objetos” e fizer um findById na entidade Aluno? S  O Hibernate vai recuperar todas as informações do Aluno, +todas as informações dos tipo de alunos + todas as informações das disciplinas associadas ao aluno + todas as informações das entidades associadas a disciplinas e assim sucessivamente, até o nível máximo definido nas configurações do Hibernate S  Multiplique por 1000 usuários fazendo essa consulta. Já viu o problema ne?
  8. 8. Hibernate Otimizado S  Já sei! Troco o mapeamento de EAGER para LAZY. S  Resolve em parte, o Hibernate não irá trazer os dados dos relacionamentos, porém a cada vez que você fizer aluno.getDisciplinas() com a sessão aberta ele gerará N consultas extras para recuperar as disciplinas. Onde N é o número de disciplinas no aluno. S  Se no sistema existem 1000 alunos consultando suas disciplinas e, em média, cada aluno está matriculado em 5 disciplinas, em vez de 1.000 consultas banco, o Hibernate gerará 1.000 iniciais + 5.000 consultas para recuperar informações da disciplinas
  9. 9. Hibernate Otimizado S  Se a sessão do Hiberante já estiver fechada, você passará por um problema bastante conhecido de LazyInitializationException. E um erro será gerado para o usuário
  10. 10. Hibernate Otimizado S  Então como eu resolvo isso? S  Simples! Mapeie tudo o LAZY, faça projeção das suas consultas, recupere apenas os dados necessários e popule o seu objeto. SELECT aluno.id, aluno.nome, tipo.descricao FROM Aluno aluno INNER JOIN aluno.tipo tipo WHERE aluno.id = :idAluno
  11. 11. Hibernate Otimizado S  Essa consulta irá retornar uma lista de arrays de objetos List<Object[]> dados= q.list(); S  Existem alguns métodos utilitário que podem ser usado para popular os objetos a partir a lista retorna pela consulta
  12. 12. Hibernate Otimizado S Isso resolverá 90% dos problemas de performance do seu sistema S Mas é muito trabalho? Eu sei! mas você quer qualidade no seu sistema ou não?
  13. 13. Hibernate Otimizado S  Quando eu falo em adicionar projeção são significa fazer isso: SELECT aluno.* FROM Aluno aluno WHERE aluno.id = :idAluno S  Isso não é fazer projeção!
  14. 14. Hibernate Otimizado S  E os outros 10% ? S  Esses 10% entram os caos de uso que são muitos usado ou casos de uso onde o requisito de performance é fundamental S  Nestes casos você deve utilizar diretamente SQL e tem que “escovar os bits” da sua consulta SQL para ver como ela pode ser otimizada S  O Hibernate nesses casos dá nem pro gasto.
  15. 15. Hibernate Otimizado S  Como eu sei o que otimizar? S  Por exemplo, no PostgreSQL existe uma opção chamada “Explain Query" que mostra como o banco está realizando a sua consulta S  No exemplo a seguir a consulta SQL deveria retorna os 20 primeiros resultados de um JOIN entre duas tabelas
  16. 16. Hibernate Otimizado SELECT s.id_servidor, p.id_pessoa FROM rh.servidor JOIN JOIN comum.pessoa p ON.... WHERE ..... LIMIT 20
  17. 17. Hibernate Otimizado S  Apesar da quantidade de dados retornado ser pequena, o limite só pode ser aplicado depois que as condições do JOIN foram testadas, então o Banco de dados irá realizar o Seq Scan em todas as tabelas para realizar o JOIN. S  Seq Scan em tabelas grandes sempre é um problema S  Isso quer dizer que ele precisa percorrer varias tabelas com milhares de resultados para realizar a consulta. O que demora em média 500ms. S  Super rápido, mas pense que 100 usuários podem estar utilizando essa consulta, então são 50 segundos em produção de uso do banco de dados.
  18. 18. Hibernate Otimizado
  19. 19. Hibernate Otimizado S  Como eu só quero um conjunto pequeno de dados, a saída foi realizar uma sub consulta menor antes, que restringisse o meu conjunto de resultados antes de realizar o JOINs da consulta principal
  20. 20. Hibernate Otimizado SELECT s.id_servidor, p.id_pessoa FROM rh.servidor JOIN JOIN comum.pessoa p ON.... WHERE s.id_servidor IN ( ------------------------------------------------- --- Otimização, só recupera desse conjunto pequeno de dados --- SELECT s.id_servidor FROM ... WHERE ... LIMIT 100 ------------------------------------------------- ) LIMIT 20
  21. 21. Hibernate Otimizado S  Isso fez o tempo da consulta cair de 500ms para 17ms. Que para 100 usuários o tempo total de uso do banco cai de 50 segundos para 1,7segudos.
  22. 22. Hibernate Otimizado S  Outro exemplo de otimização de consultas SQLs S  Tenho um problema onde se deveria verificar se um usuário estava entre os resultados retornados por uma determina consulta. S  Como isso foi realizado a princípio?
  23. 23. Hibernate Otimizado SELECT count(id_pessoa) FROM comum.pessoa p WHERE 123456 – id da pessoa a ser testado IN( --- consulta interna select p.id_pessoa FROM .... )
  24. 24. Hibernate Otimizado S  Porém essa consulta interna pode retornar um número muito grande dados, na ordem de 2.000.000 de ids para verificar se o usuário que você quer, está dentro desse conjunto S  Resultado: 1 segundo a consulta x 100 usuários : 100 segundos de uso do banco. S  Será que não existe uma maneira mais otimizada de fazer isso?
  25. 25. Hibernate Otimizado S  Se você parar para pensar um pouco, verá que se eu quero verificar se um determinado usuário está no grupo da consulta é só verificar se: ( count(*) consulta AND meu usuário ) > 0
  26. 26. Hibernate Otimizado SELECT count(interna.id_pessoa) FROM ( -- consulta anterior select p.id_pessoa FROM comum.pessoa p INNER JOIN .... -- e meu usuário AND p.id_pessoa = 123456 ) as interna
  27. 27. Hibernate Otimizado S  Resultado: De 1 segundo o tempo da consulta caiu para 17ms , para 100 usuários : 1,7 segundos de uso do banco. +- 5.800 % de ganho do tempo da consulta. Só isso. É pouco?
  28. 28. Hibernate Otimizado S  Conclusões S  O Hibernate se tornou o framework padrão para mapeamento objeto relacional, porém o seu mau uso trás sérios problemas de performance ao sistema. S  O mapeamento dos relacionamentos do domínio como LAZY e a recuperação apenas das informações necessárias ao seu caso de uso resolve 90% das questões de performance do seu sistema S  Os demais 10%, onde o requisito de performance é fundamental, deve abandonar o Hibernate e analisar os pontos mais demorados da sua consulta e tentar descobrir maneiras de otimizá-la S  Esses 10% vai muito da experiência e habilidade do desenvolvedor
  29. 29. Hibernate Otimizado S  Conclusões S  Falei apenas das otimizações em relação ao tempo das consultas, existe ainda outras maneiras de otimizar consultas como criar cache em memória ou desnormalização das tabelas do banco de dados. Ou ainda, em casos específicos, o uso de banco de dados não relacionais.
  30. 30. S Usando Hibernate de Forma Otimizada Jadson Santos

×