Como extrair o máximo de seu confinamento usando de forma simples bases de gestão
Usando hiberante de forma otimizada
-
Upload
jadson-santos -
Category
Software
-
view
80 -
download
7
description
Transcript of Usando hiberante de forma otimizada
S
Usando Hibernate de Forma Otimizada
Jadson Santos
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.
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!
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; }
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.
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; }
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?
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
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
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
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
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?
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!
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.
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
Hibernate Otimizado
SELECT s.id_servidor, p.id_pessoa
FROM rh.servidor
JOIN JOIN comum.pessoa p ON....
WHERE .....
LIMIT 20
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.
Hibernate Otimizado
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
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
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.
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?
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 ....
)
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?
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
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
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?
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
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.
S
Usando Hibernate de Forma Otimizada
Jadson Santos