Analise de desempenho dos frameworks de - ESPWEB

Propaganda
Análise de Desempenho dos Frameworks de Persistência
Hibernate e Spring Data
1
Vitor Gotardo , Edson A. Oliveira Junior
2
Resumo. Grande parte das aplicações desenvolvidas utilizando linguagens orientadas a objetos
persistem seus objetos por meio de bases de dados relacionais com o apoio de frameworks de
Mapeamento Objeto-Relacional (ORM), como Hibernate. Este artigo apresenta uma análise de
desempenho baseada em benchmark dos frameworks Hibernate e Spring Data. Tal análise
fornece indícios iniciais para que analistas e desenvolvedores possam escolher os frameworks
mais apropriados para o desenvolvimento de seus projetos.
Palavras-chave: framework, ORM, Hibernate, JPA, Spring Data, benchmark.
Abstract. Most applications developed using object-oriented languages persist your objects using
relational databases with support of Object-Relational Mapping (ORM) frameworks such as
Hibernate. This paper presents a benchmark-based performance analysis for Hibernate and Spring
Data frameworks. Such an analysis provides initial evidence to analysts and developers may
choose the most appropriate frameworks for the development of their projects.
Keywords: framework, ORM, Hibernate, JPA, Spring Data, benchmark.
1. Introdução
Muitas aplicações utilizam dados que precisam ser guardados e recuperados, em
um ambiente orientado a objetos. Os objetos são utilizados para representar esses
dados, e nesse caso, é o objeto que precisa ser armazenado. Para tanto, existem três
tipos de mecanismos de persistência de objetos: Object-Oriented Database Management
Systems (OODBMS), Relational Database Management Systems (RDBMS) e ObjectRelational Database Management Systems (ORDMS) [1].
Um problema muito conhecido na persistência de objetos em um banco de dados
relacional é o conflito de impedância, que surge entre o modelo orientado a objeto e o
modelo relacional e também entre a linguagem orientada a objeto e a linguagem de
consulta (query) relacional [1]. Conflito de impedância é quando dois sistemas diferentes
não funcionam de maneira ideal e eficiente quando conectados para funcionarem em
conjunto. Poderíamos dizer então que os conceitos de modelo de orientação a objeto e
do modelo relacional possuem valores de impedância diferentes. Enquanto o modelo
relacional dá mais ênfase aos dados em si e sua representação e organização, o modelo
orientado a objetos enfoca na abstração dos dados e seu comportamento, operações na
forma de objetos [7].
O Mapeamento Objeto-Relacional (Object-Oriented Mapping - ORM) foi
desenvolvido para servir como uma ponte entre esse conflito de impedância e tornar a
persistência de objetos mais simples. Assim, é oferecido um mapeamento entre o
modelo orientado a objeto e o modelo relacional [1].
1
Aluno do curso de especialização em Desenvolvimento de Sistemas para Web – Universidade Estadual de
Maringá (UEM) - Av. Colombo, 5790 – Bloco C56 – Maringá – PR – Brasil – [email protected]
2
Departamento de Informática – Universidade Estadual de Maringá (UEM) - Av. Colombo, 5790 – Bloco
C56 – Maringá – PR – Brasil - [email protected]
1
Este artigo tem como meta comparar dois frameworks ORM, o Hibernate que é
um dos mais consolidados por desenvolvedores Java e .NET e o Spring Data JPA que é
um framework recente, mas que promete agilizar o desenvolvimento da camada de
persistência. Para tal comparação serão utilizados algumas operações de persistência
sendo elas: consultas simples e com joins, inserção, alteração e exclusão. Será utilizado
uma média do desempenho dos procedimentos executados para encontrar o framework
com menor tempo médio nas operações de persistência.
Este artigo está organizado da seguinte forma: na Seção 2 são abordadas as
tecnologias utilizadas para efetuar a comparação dos frameworks; na Seção 3 é
realizado o estudo comparativo de desempenho entre Hibernate e Spring Data JPA; na
Seção 4 é apresentada a conclusão e trabalhos que podem ser desenvolvidos
futuramente.
2. Revisão Bibliográfica
2.1. Hibernate
O Hibernate é um projeto que tem como objetivo ser uma solução completa para
o problema de mapeamento persistindo dados em Java. Ele serve como mediador na
interação de aplicações com banco de dados relacional, deixando o desenvolvedor livre
para concentrar-se na camada de negócio da aplicação. O Hibernate é uma solução não
intrusiva. O desenvolvedor não precisa seguir todas as regras e design patterns quando
estiver desenvolvendo a camada lógica de negócio e classes de persistência, mas, o
Hibernate se integra facilmente com a maioria das novas e existentes aplicações e não
requer grandes mudanças na aplicação [9].
2.2. Spring Data JPA
O Spring oferece suporte para as tecnologias de acesso a dados desde seu
início. Este oferece uma implementação mais simples de acesso a dados, independente
da tecnologia utilizada como JDBC, Hibernate, TopLink, JDO e iBatis para a persistência
de dados.
O principal alvo do Spring em relação a acesso a dados era bancos de dados
relacionais, sendo que esta tecnologia era predominante quando se trata de persistência
de dados. Com a chegada da tecnologia NoSQL a espaço para criar suporte para
desenvolvedores surgiu. Além disso, ainda existem melhorias a serem feitas
relacionadas ao acesso a dados relacionais. Foram esses fatores que incentivaram a
criação do projeto Spring Data que consiste em módulos dedicados para tecnologias
como NoSQL, JPA e módulos JDBC para suporte a banco de dados relacional [12].
O projeto Spring Data JPA, embora não seja um framework ORM, foi
desenvolvido com base no padrão JPA 2 para trabalhar com qualquer framework que
siga tal especificação.
O Spring Data JPA é responsável pela criação das classes Data Access Object
(DAO) que possuem os métodos concretos para comunicação com a base de dados.
Assim, fica abstraída a necessidade de se criar classes concretas para os
repositórios de dados, sendo necessário apenas criar uma interface específica para cada
classe de entidade, e nelas, estender a interface JpaRepository [3].
2.3. Benchmark Employees Sample Database
O benchmark é um teste, ou uma série de testes, que medem o desempenho de
um sistema ou subsistema enquanto executam tarefas definidas. O benchmark deve
medir o pico de desempenho de um sistema, normalmente operações com um problema
conhecido. Benchmarks medem a capacidade de um sistema, muitas vezes referente a
performance de uma aplicação em particular, como um banco de dados [11].
2
Neste artigo o benchmark é utilizado para medir o desempenho de frameworks
ORM efetuando operações de persistência em banco de dados relacional, assim,
tornando possível a comparação entre eles.
A base de dados Employee Sample Database foi desenvolvida por Crews e Maxia
[4] e fornece aproximadamente 160MB de dados que estão separados em seis tabelas,
fornecendo um total de 4 milhões de registros. Tal benchmark é bastante interessante
para realizar tarefas de comparação de mecanismos de persistência de dados.
2.4. Java Persistence Query Language
Em muitas maneiras o JPQL é similar ao SQL, uma ferramenta para interagir com
base de dados relacional.
Além disso, o JPQL é similar ao SQL em sua sintaxe, declarações e cláusulas. A
principal diferença entre JPQL e SQL esta nos objetos que são especificados nas
declarações e o objeto retornado por esta declaração. Em declarações SQL, é definido
diretamente o objeto que deseja utilizar, por exemplo, uma tabela ou view para ser
consultada ou modificada. Em declarações JQPL são utilizadas as entidades. E o mesmo
acontece para os resultados retornados pela consulta JQPL, estes são instâncias de
entidades, enquanto que os resultados retornados pelo SQL são tabelas ou views.
Resumindo, o JQPL trata as entidades mapeadas para uma estrutura de base de dados,
não precisando lidar com a estrutura da base de dados diretamente.
O JQPL simplifica muito a tarefa de recuperar entidades. Todas as instâncias de
entidades retornadas são automaticamente mapeadas. Assim, não é necessário mapear
estas instâncias manualmente [10].
2.5. Anotação @Query
A anotação @Query pode ser utilizada para criar consultas usando JPA e vincular
esta consulta a um método na interface dos repositórios. Assim, quando o método é
chamado, o Spring Data JPA executa a consulta especificada na anotação @Query [6].
3. Estudo Comparativo de Desempenho entre Hibernate e Spring Data JPA
3.1. Ambiente de Testes
Para efetuar os testes de benchmark foi utilizado:
•
Spring Tool Suite 3.3.0 como ambiente de desenvolvimento integrado (IDE)
•
Spring Framework 3.1.1
•
Hibernate 4.2.2;
•
Spring Data JPA 1.3.4;
•
MySQL 5.5.24;
•
Java JDK 1.7;
•
Maven 3.0.5 para construir os projetos mais facilmente mantendo as versões dos
pacotes utilizados sempre estáveis e garantir que as mesmas versões foram
utilizadas para os dois projetos.
O computador usado para os testes tem processador [email protected] com 4 núcleos
reais e 8 threads, e 16GB de memoria RAM.
3.2. Planejamento, Execução e Análise dos Resultados
3
3.2.1 Definição de Contexto e Planejamento do Estudo Comparativo
3.2.1.1 Objetivo do Estudo
Comparar frameworks de persistência objeto-relacional com o objetivo de
identificar o melhor desempenho com relação a operações de persistência de dados em
um banco de dados relacional do ponto de vista de analistas e desenvolvedores de
software no contexto de um benchmark específico para operações de persistência
relacionais.
3.2.1.2 Seleção das Variáveis
•
Variáveis independentes (entrada/causa):
o
•
Framework de persistência – Hibernate e Spring Data JPA
Variável dependente (observação/efeito):
o
Desempenho
3.2.1.3 Definição das Hipóteses
•
Hipótese Nula (H0): os tempos médios para a execução das operações
de persistência usando Hibernate e Spring Data JPA são os mesmos.
•
Hipótese Alternativa (H1): o tempo médio de execução das operações
de persistência usando Hibernate é menor que o tempo médio usando
Spring Data JPA.
•
Hipótese Alternativa (H2): o tempo médio de execução das operações
de persistência usando Hibernate é maior que o tempo médio usando
Spring Data JPA.
3.2.2 Execução do Estudo Comparativo
O estudo comparativo foi conduzido com base na execução de 14 operações de
persistência, sendo 11 consultas (query1 a query11), sendo que as consultas (query3 e
query5) possuem JOIN e as demais são consultas simples, 1 inserção, 1 alteração e 1
exclusão. Cada consulta foi executada 10 vezes manualmente, sendo efetuado o cálculo
médio do desempenho de cada consulta para ter uma ideia geral dos resultados.
Query1: é uma consulta simples que busca 1 Employee em um total de 10.000
registros. Foi utilizado somente a tabela employees da base de dados e o comando
utilizado para esta consulta foi: “@Query("FROM Employee e WHERE e.id =
249359")”. Como mostra a Figura 1 o Hibernate efetuou a consulta em 0,163s e o
Spring Data JPA efetuou a consulta em 0,048s.
4
0,2
0,163
0,15
0,1
0,048
0,05
0
Hibernate
SpringData JPA
Figura 1: Busca 1 Employee em um total de 10.000 registros.
Query2: é uma consulta simples que busca 10.000 registros do tipo Employee
que possuam o ID maior que 20.000 utilizando o operador “>”. Foi utilizado somente a
tabela employees da base de dados e o comando utilizado para esta consulta foi:
“@Query("FROM Employee e WHERE e.id > 20000")”. Como mostra a Figura 2 o
Hibernate efetuou a consulta em 1,006s e o Spring Data JPA efetuou a consulta em
1,087s.
1,087
1,1
1,08
1,06
1,04
1,02
1,006
1
0,98
0,96
Hibernate
SpringData JPA
Figura 2: Busca 10.000 registros do tipo Employee com ID maior que
20.000.
Query3: é uma consulta com JOIN que busca 10.000 registros do tipo Employee
que possuam o ID maior que 20.000 e estão no Department de ID 7, os resultados estão
ordenados pela data de início e de término que determinado Employee permaneceu no
departamento. Foram utilizadas as tabelas employees e dept_emp e o comando utilizado
para esta consulta foi: “@Query("FROM Employee e INNER JOIN e.deptEmps de
WHERE e.id > 20000 AND de.pk.department = 7 ORDER BY de.from_date,
de.to_date")”. Como mostra a Figura 3, o Hibernate efetuou a consulta em 3,826s e o
Spring Data JPA efetuou a consulta em 3,536s.
5
3,9
3,826
3,8
3,7
3,6
3,536
3,5
3,4
3,3
Hibernate
SpringData JPA
Figura 3: Busca 10.000 registros do tipo Employee com ID maior que
20.000 que estão no Department de ID 7, ordenados pelas datas de início e
término.
Query4: é uma consulta simples que busca 10.000 registros do tipo Employee
que possuam o ID maior ou igual a 20.000 utilizando o operador “>=”. Foi utilizado
somente a tabela employees da base de dados e o comando utilizado para esta consulta
foi: “@Query("FROM Employee e WHERE e.id >= 20000")”. Como mostra a Figura 4, o
Hibernate efetuou a consulta em 1,021s e o Spring Data JPA efetuou a consulta em
1,055s.
1,055
1,06
1,05
1,04
1,03
1,021
1,02
1,01
1
Hibernate
SpringData JPA
Figura 4: Busca 10.000 registros do tipo Employee com ID maior ou igual
que 20.000.
Query5: é uma consulta com JOIN que busca 10.000 registros do tipo Employee
que estão no Department de ID 7. Foi utilizado as tabelas employees e dept_emp e o
comando utilizado para esta consulta foi: “@Query("FROM Employee e INNER JOIN
e.deptEmps de WHERE de.pk.department = 7")”. Como mostra a Figura 5, o
Hibernate efetuou a consulta em 3,787s e o Spring Data JPA efetuou a consulta em
3,470s.
6
3,9
3,787
3,8
3,7
3,6
3,47
3,5
3,4
3,3
Hibernate
SpringData JPA
Figura 5: Busca 10.000 registros do tipo Employee que estão no
Department de ID 7.
Query6: é uma consulta simples que busca 10.000 registros do tipo Employee
que possuam o ID menor que 20.000 utilizando o operador “<”. Foi utilizado somente a
tabela employees da base de dados e o comando utilizado para esta consulta foi:
“@Query("FROM Employee e WHERE e.id < 20000")”. Como mostra a Figura 6, o
Hibernate efetuou a consulta em 0,997s e o Spring Data JPA efetuou a consulta em
1,064s.
1,08
1,064
1,06
1,04
1,02
0,997
1
0,98
0,96
Hibernate
SpringData JPA
Figura 6: Busca 10.000 registros do tipo Employee com ID menor que
20.000.
Query7: é uma consulta simples que busca 10.000 registros do tipo Employee que
possuam o ID menor ou igual a 20.000 utilizando o operador “<=”. Foi utilizado somente a
tabela employees da base de dados e o comando utilizado para esta consulta foi:
“@Query("FROM Employee e WHERE e.id <= 20000")”. Como mostra a Figura 7, o
Hibernate efetuou a consulta em 1,007s e o Spring Data JPA efetuou a consulta em
1,041s.
1,05
1,041
1,04
1,03
1,02
1,01
1,007
1
0,99
Hibernate
SpringData JPA
Figura 7: Busca 10.000 registros do tipo Employee com ID menor ou igual
que 20.000.
7
Query8: é uma consulta simples que busca 10.000 registros do tipo Employee
que possuam o ID diferente de 20.000 utilizando o operador “<>”. Foi utilizado somente a
tabela employees da base de dados e o comando utilizado para esta consulta foi:
“@Query("FROM Employee e WHERE e.id <> 20000")”. Como mostra a Figura 8, o
Hibernate efetuou a consulta em 1,006s e o Spring Data JPA efetuou a consulta em
1,037s.
1,037
1,04
1,03
1,02
1,01
1,006
1
0,99
Hibernate
SpringData JPA
Figura 8: Busca 10.000 registros do tipo Employee com ID diferente de
20.000.
Query9: é uma consulta simples que busca 10.000 registros do tipo Employee que
possuam o ID entre 25.000 e 50.000 utilizando o operador BETWEEN. Foi utilizado
somente a tabela employees da base de dados e o comando utilizado para esta consulta
foi: “@Query("FROM Employee e WHERE e.id BETWEEN 25000 AND 50000")”. Como
mostra a Figura 9, o Hibernate efetuou a consulta em 0,998s e o Spring Data JPA
efetuou a consulta em 1,033s.
1,04
1,033
1,03
1,02
1,01
1
0,998
0,99
0,98
Hibernate
SpringData JPA
Figura 9: Busca 10.000 registros do tipo Employee com ID entre 25.000 e
50.000.
Query10: é uma consulta simples que busca 10.000 registros do tipo Employee
que são do GENDER(sexo) masculino(M) utilizando o operador IN. Foi utilizado somente
a tabela employees da base de dados e o comando utilizado para esta consulta foi:
“@Query("FROM Employee e WHERE e.gender IN('M')")”. Como mostra a Figura 10,
o Hibernate efetuou a consulta em 0,999s e o Spring Data JPA efetuou a consulta em
1,030s.
8
1,04
1,03
1,03
1,02
1,01
0,999
1
0,99
0,98
Hibernate
SpringData JPA
Figura 10: Busca 10.000 registros do tipo Employee que são do sexo
masculino.
Query11: é uma consulta simples que busca 10.000 registros do tipo Employee que
possuam primeiro nome com as letras “Sa” utilizando o operador LIKE. Foi utilizado
somente a tabela employees da base de dados e o comando utilizado para esta consulta
foi: “@Query("FROM Employee e WHERE e.first_name LIKE '%Sa%'")”. Como
mostra a Figura 11, o Hibernate efetuou a consulta em 1,039s e o Spring Data JPA
efetuou a consulta em 1,066s.
1,066
1,07
1,06
1,05
1,039
1,04
1,03
1,02
Hibernate
SpringData JPA
Figura 11: Busca 10.000 registros do tipo Employee que possuam “Sa” no
primeiro nome.
Query12: foram inseridos 1.000 objetos do tipo Employee na tabela employees.
Todas as propriedades do objeto foram preenchidas, sendo elas: first_name, last_name,
gender, hire_date, birth_date. Como mostra a Figura 12, o Hibernate efetuou a inserção
em 0,701s e o Spring Data JPA efetuou a inserção em 5,930s.
7
5,93
6
5
4
3
2
1
0,701
0
Hibernate
SpringData JPA
Figura 12: Inserção de 1.000 objetos do tipo Employee.
9
Query13: foram alterados os últimos 10.000 registros do tipo Employee, os campos
alterados foram: first_name, last_name, gender. Como mostra a Figura 13, o Hibernate
efetuou a operação em 0,177s e o Spring Data JPA efetuou a operação em 0,078s.
0,2
0,177
0,15
0,1
0,078
0,05
0
Hibernate
SpringData JPA
Figura 13: Alteração dos últimos 10.000 registros do tipo Employee.
Query14: foram excluídos os últimos 10.000 registros do tipo Employee. Como
mostra a Figura 14, o Hibernate efetuou a operação em 0,247s e o Spring Data JPA
efetuou a operação em 0,147s.
0,3
0,247
0,25
0,2
0,147
0,15
0,1
0,05
0
Hibernate
SpringData JPA
Figura 14: Exclusão dos últimos 10.000 registros do tipo Employee.
3.2.3 Análise dos Dados do Estudo Comparativo
Com base na execução das 14 operações de persistência realizadas neste estudo
o Hibernate obteve melhor desempenho em 9 operações. O Spring Data JPA obteve
melhor desempenho em 5 operações. Sendo assim, o framework Hibernate obteve o
melhor desempenho geral com base nas operações utilizadas neste estudo. A Tabela 1
mostra o desempenho dos frameworks categorizados por tipo de operação.
Cláusulas
Hibernate
Spring Data JPA
WHERE
8
1
JOIN
x
2
INSERT
1
x
UPDATE
x
1
10
DELETE
x
1
Total
9
5
Tabela 1: Desempenho dos frameworks categorizados por tipo de
operação.
Assim, o estudo realizado fornece indícios de que a hipótese nula (H0) deve ser
rejeitada e, consequentemente, a hipótese alternativa (H1) deve ser aceita, sendo que na
média, o framework Hibernate obteve melhor desempenho do que o framework Spring
Data JPA para as operações realizadas neste estudo. O resultado do desempenho geral
dos frameworks pode ser visto na Figura 15.
2
1,544
1,5
1,199
1
0,5
0
Hibernate
SpringData JPA
Figura 15: Desempenho geral dos frameworks.
4. Conclusões e Trabalhos Futuros
Este artigo apresentou uma análise de desempenho baseada em benchmark por
meio de uma série de operações de persistência com o intuito de fornecer evidências
iniciais podendo guiar analistas e gerentes na escolha do framework de persistência mais
adequado para os seus projetos.
Com base nos resultados obtidos pode-se observar uma ligeira vantagem na
utilização do Hibernate com relação ao Spring Data para o conjunto de operações
definidas pelo benchmark utilizado.
Como direção a trabalhos que podem ser desenvolvidos futuramente tem-se: (i) a
análise do desempenho em um sistema multiusuário; (ii) planejamento e realização de
uma análise comparativa utilizando benchmarks com operações de persistência mais
complexas; (iii) estudo comparativo dos diferentes tipos de linguagem de queries
suportadas pelos frameworks; e (iv) comparação de funcionalidades entre os
frameworks.
Referências Bibliográficas
[1] PIETER VAN ZYL, DERRICK G. KOURIE, ANDREW BOAKE – Comparing the Performance
of Object Databases and ORM Tools. Disponível em: <http://odbms.org/download/027.01 Zyl
Comparing the Performance of Object Databases and ORM Tools September 2006.PDF>. Acesso
em: 10, set, 2013.
[2] MIKAEL KOPTEFF – The Usage and Performance of Object Databases compared with
ORM tools in a Java environment. Disponível em: <http://www.odbms.org/download/045.01
11
Kopteff The Usage and Performance of Object Databases Compared with ORM Tools in a Java
Environment March 2008.PDF>. Acesso em: 10, set, 2013.
[3] MARCIO BALLEM S. – Persistencia com Spring Data JPA. Disponível em:
<http://www.devmedia.com.br/persistencia-com-spring-data-jpa-revista-java-magazine-103/24390>.
Acesso em: 10, set, 2013.
[4] MYSQL – Employees Sample Database – Introduction. Disponível em:
<http://dev.mysql.com/doc/employee/en/employees-introduction.html>. Acesso em: 11, set, 2013.
[5]
ORACLE
–
The
Java
Persistence
Query
Language.
Disponível
em:
<http://docs.oracle.com/javaee/6/tutorial/doc/bnbtg.html>. Acesso em: 11, set, 2013.
[6] PETRI KAINULAINEN – Spring Data JPA Tutorial Part Three: Custom Queries with Query
Methods. Disponível em: <http://www.petrikainulainen.net/programming/spring-framework/springdata-jpa-tutorial-three-custom-queries-with-query-methods/>. Acesso em: 01, out, 2013.
[7] DIOGO V. DOS SANTOS, MARCELO DE R. MARTINS – Métricas para avaliação das
alternativas de persistência de dados num ambiente objeto relacional. São Paulo: IME/USP,
2007.
[8] SHOAIB MAHMOOD BHATTI, ZAHID HUSSAIN ABRO, FARZANA RAUF ABRO –
Performance Evaluation of Java Based Object Relational Mapping Tools. Disponível em:
<http://publications.muet.edu.pk/research_papers/pdf/pdf755.pdf>. Acesso em: 16, nov, 2013.
[9] CHRISTIAN BAUER, GAVIN KING – Java Persistence with Hibernate. Manning Publications,
Revised edition, p. 4, 2006.
[10] YULI VASILIEV – Beginning Database-Driven Application Development in Java EE: Using
GlassFish. Apress, 1 edition, p. 283 – 284, 2008.
[11] MIKE AULT, DONALD K. BURLESON, CLAUDIA FERNANDEZ, KEVIN KLEIN, BERT
SCALZO - Database Benchmarking: Practical Methods for Oracle & SQL Server. Rampant
Techpress, PAP/CDR edition, p. 19, 2007.
[12] JONATHAN L. BRISBIN, OLIVER GIERKE, THOMAS RISBERG, MARK POLLACK, MICHAEL
HUNGER – Spring Data. O'Reilly Media, 1 edition, p. 3, 2012.
12
Download