Mybatis vs hibernate, which performance is better?

Java technology stack 2021-09-15 04:28:55
mybatis vs hibernate performance better


author : Zheng muxing

source :https://zhuanlan.zhihu.com/p/21966051

Preface

Because the programming idea is different from the database design pattern , Some of them have been born ORM frame .

The core is to transform relational database and data into object type . The current popular solutions are Hibernate And myBatis.

Both have advantages and disadvantages . Competition is fierce , One of the more important considerations is performance .

So the author through various experiments , Two performance related indices under the same scenario are measured , For your reference .

Friendship tips : If you think the article is too long , You can pull to the end of the text to see the conclusion .

Test target

The following test needs to determine a few points :

Performance difference scenarios ;

Performance is not different in the same scenario ;

Find out the advantages and disadvantages of each frame , Performance in various situations , Applicable scenario .

Test ideas

The test population is divided into : Single table insert , Association insertion , Single table query , Multi-table query .

There are two rounds of testing , Do one round with the default parameters in the scene , A round of tuning and strengthening , This paper makes a comparative analysis of .

Ensure the consistency of input and output in the test .

The sample size should be as large as possible , achieve 10 Above 10000 level , Reduce statistical error .

Test outline

In specific scenarios

Insert the test 1:10 Ten thousand records are inserted into .

Query test 1:100 In ten thousand data, the single table passes through id Inquire about 100000 Time , No associated fields .

Query test 2:100 In ten thousand data, the single table passes through id Inquire about 100000 Time , Output associated object field .

Query test 3:100 ten thousand *50 Million linked data query 100000 Time , Both output the same fields .

Get ready

database :mysql 5.6

Form design :

twitter: twitter

CREATE TABLE `twitter` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`add_date` datetime DEFAULT NULL,
`modify_date` datetime DEFAULT NULL,
`ctx` varchar(255) NOT NULL,
`add_user_id` bigint(20) DEFAULT NULL,
`modify_user_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `UPDATE_USER_FORI` (`modify_user_id`),
KEY `ADD_USER_FORI` (`add_user_id`),
CONSTRAINT `ADD_USER_FORI` FOREIGN KEY (`add_user_id`) REFERENCES `user` (`id`) ON DELETE SET NULL,
CONSTRAINT `UPDATE_USER_FORI` FOREIGN KEY (`modify_user_id`) REFERENCES `user` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=1048561 DEFAULT CHARSET=utf8

user: user

CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=524281 DEFAULT CHARSET=utf8

Test data preparation :

Table 1 :twitter

No data .

Table two :user

50 10000 random user names .

Random content tweets (material_twitter)

nothing id, Only random string content , common 10 Ten thousand .

Used to insert control tweet table .

Generate data code , relation 100 Users :

insert into twitter(ctx,add_user_id,modify_user_id,add_date,modify_date)
SELECT name,ROUND(RAND()*100)+1,ROUND(RAND()*100)+1,'2016-12-31','2016-12-31'
from MATERIAL

Generate data code , relation 500000 Users :

insert into twitter(ctx,add_user_id,modify_user_id,add_date,modify_date)
SELECT name,ROUND(RAND()*500000)+1,ROUND(RAND()*500000)+1,'2016-12-31','2016-12-31'
from MATERIAL

Entity code

@Entity
@Table(name = "twitter")
public class Twitter implements java.io.Serializable{
private Long id;
private Date add_date;
private Date modify_date;
private String ctx;
private User add_user;
private User modify_user;
private String createUserName;
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Temporal(TemporalType.DATE)
@Column(name = "add_date")
public Date getAddDate() {
return add_date;
}
public void setAddDate(Date add_date) {
this.add_date = add_date;
}
@Temporal(TemporalType.DATE)
@Column(name = "modify_date")
public Date getModifyDate() {
return modify_date;
}
public void setModifyDate(Date modify_date) {
this.modify_date = modify_date;
}
@Column(name = "ctx")
public String getCtx() {
return ctx;
}
public void setCtx(String ctx) {
this.ctx = ctx;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "add_user_id")
public User getAddUser() {
return add_user;
}
public void setAddUser(User add_user) {
this.add_user = add_user;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "modify_user_id")
public User getModifyUser() {
return modify_user;
}
public void setModifyUser(User modify_user) {
this.modify_user = modify_user;
}
@Transient
public String getCreateUserName() {
return createUserName;
}
public void setCreateUserName(String createUserName) {
this.createUserName = createUserName;
}
}

Start

Insert the test 1

Code operation :

Load random content twitter table data into memory , And then, one by one, they add to the twitter list , common 10 Ten thousand .

Key code :

hibernate:

Session session = factory.openSession();
session.beginTransaction();
Twitter t = null;
Date now = new Date();
for(String materialTwitter : materialTwitters){
// System.out.println("materialTwitter="+materialTwitter);
t = new Twitter();
t.setCtx(materialTwitter);
t.setAddDate(now);
t.setModifyDate(now);
t.setAddUser(null);
t.setModifyUser(null);
session.save(t);
}
session.getTransaction().commit();

mybatis:

Twitter t = null;
Date now = new Date();
for(String materialTwitter : materialTwitters){
// System.out.println("materialTwitter="+materialTwitter);
t = new Twitter();
t.setCtx(materialTwitter);
t.setAddDate(now);
t.setModifyDate(now);
t.setAddUser(null);
t.setModifyUser(null);
msession.insert("insertTwitter", t);
}
msession.commit();

TwitterMapper.xml, Insert code snippet :

<insert id="insertTwitter" keyProperty="id" parameterType="org.pushio.test.show1.entity.Twitter" useGeneratedKeys="true">
insert into twitter(ctx, add_date,modify_date) values (#{ctx},#{add_date},#{modify_date})
</insert>

Query test 1

adopt id from 1 Increase to 10 Wan queries twitter content in turn , Only output microblog content .

Key code :

hibernate:

long cnt = 100000;
for(long i = 1; i <= cnt; ++i){
Twitter t = (Twitter)session.get(Twitter.class, i);
//System.out.println("t.getCtx="+ t.getCtx() + " t.getUser.getName=" + t.getAddUser().getName());
}

mybatis:

long cnt = 100000;
for(long i = 1; i <= cnt; ++i){
Twitter t = (Twitter)msession.selectOne("getTwitter", i);
//System.out.println("t.getCtx="+ t.getCtx() + " t.getUser.getName=" + t.getAddUser().getName());
}

Query test 2

And query testing 1 The whole thing is the same , Add the creator name field of microblog , Here we need to associate .

The corresponding microblog is 10 Million users . Maybe some users repeat . The corresponding number of users here may be the same as hibernate The configuration of lazy loading has an impact on .

This shows hibernate A convenient place for , You can go directly through getAddUser() You can get user Related fields .

However myBatis You need to write a new vo, So testing batis When it comes to Twitter Add the name of the creator to the entity (createUserName).

here hibernate Will test for lazy loading respectively , No lazy loading .

mybatis Will test both default and cache conditions .

among mybatis It is difficult to configure the cache mechanism of , Not for real business ( There may be dirty data ), This is for reference only .

When testing , There are two scenarios for the number of users associated with twitter , One is that Twitter is associated with 100 Users , It's different tweets, which are in 100 Within users , The correlation here is generated randomly .

The other is that Twitter is associated with 50 Million users , Basically 50 The information of each user will be found out .

Above “ Get ready ” You can see how the associated data is generated in .

Key code :

hibernate:

long cnt = 100000;
for(long i = 1; i <= cnt; ++i){
Twitter t = (Twitter)session.get(Twitter.class, i);
t.getAddUser().getName();// Load the corresponding fields
//System.out.println("t.getCtx="+ t.getCtx() + " t.getUser.getName=" + t.getAddUser().getName());
}

Load configuration changes quickly ,Twitter.java:

@ManyToOne(fetch = FetchType.EAGER)// Emergency loading
//@ManyToOne(fetch = FetchType.LAZY)// Lazy loading
@JoinColumn(name = "add_user_id")
public User getAddUser() {
return add_user;
}

mybatis:

for(long i = 1; i <= cnt; ++i){
Twitter t = (Twitter)msession.selectOne("getTwitterHasUser", i);
// System.out.println("t.getCtx="+ t.getCtx() + " t.getUser.getName=" + t.getCreateUserName());
}

TwitterMapper.xml To configure :

<select id="getTwitterHasUser" parameterType="long" resultType="org.pushio.test.show1.entity.Twitter">
select twitter.*,user.name as creteUserName from twitter,user
where twitter.id=#{id}
AND twitter.add_user_id=user.id
</select>

test result

Test and analysis

The test is divided into inserts , Single table query , Relational query . Association query hibernate Configure it in three situations .

In the associated field query ,hibernate In two cases , There is a big difference in performance . In the case of lazy loading , If Twitter has more users , Then the performance is better than just mapping 100 The situation of individual users is much worse .

In other words , If the number of users is small ( Total number of associated users ) when , In other words, the same user will be queried repeatedly , You don't need to do too many queries on the user table .

After querying the document , Prove that when using lazy loading , The object will be id by key Do the cache , That is to say, to inquire about 100 After users , Subsequent user information is cached , Make the performance have fundamental improvement . Even better than myBatis Higher .

If it's a connection 50 Million users , be hibernate Need to check 50 Ten thousand user information , And assemble this 50 Million users , At this point, the performance is better than myBatis Poor performance , But the difference is not big , Less than 1ms, Indicates acceptable .

among hibernate In the case of non lazy loading, and myBatis The performance difference is also larger than other tests , The average is less than 1ms.

The main reason for this difference is ,myBatis The loaded fields are clean , There are not too many extra fields , Directly reflected in the Association . take the reverse into consideration hibernate Then the word of the whole table will be loaded into the object , It also includes related user Field .

hibernate There are good and bad in this situation , It depends on the specific scene , For the management platform , There's more information to show , When concurrency requirements are not high ,hibernate Comparative advantage .

However, in some small activities , Internet sites , High concurrency ,hibernate It's not very suitable for ,myBatis+VO Is the preferred .

in addition , Official account Java Technology stack , Reply in the background : interview , I can get the MyBatis A series of interview questions and answers , Very complete .

Test summary

The overall view ,myBatis In all cases , Especially insert and single table query , Will be slightly better than hibernate. But the difference is not obvious , You can basically ignore the difference .

The big difference is when the association query ,hibernate In order to ensure POJO Data integrity , The associated data needs to be loaded , More data needs to be queried additionally . here hibernate It doesn't provide the corresponding flexibility .

A big difference in association is the lazy loading feature . among hibernate You can make special use of POJO Integrity to cache , You can save objects in the first and second level caches , If there are more queries on a single object , There will be obvious performance benefits .

When it comes to single object association , The performance can be improved by lazy loading and secondary caching .

Last , Performance and query of data orm The framework doesn't matter much , because orm It mainly helps developers transform relational data into object data model , On the deep analysis of the code ,hibernate Designed to be more heavyweight , For development, it can be regarded as redevelopment of a database , Don't let developers care too much about database features , Directly in hibernate On the basis of development , Execution is divided into sql Generate , Data encapsulation, etc , It took a lot of time here . However myBatis It's more direct than , It is mainly to do a mapping between association and output fields . among sql It's basically written , You can replace it directly , No need to be like hibernate That's how to dynamically generate the whole sql sentence .

Fortunately hibernate At this stage, it has been optimized better , There's nothing like myBatis There are too many differences in performance , But in terms of development efficiency , Scalability is relative to myBatis It's too much to say .

Last, last , About myBatis cache ,hibernate Wait a minute , I'll do a special test later .

About cache configuration

myBatis relative Hibernate And the package is more tight ORM In terms of implementation , because hibernate The operation of data objects is tightly encapsulated , It can guarantee the cache synchronization within its scope , and ibatis What is provided is a semi enclosed encapsulation implementation , Therefore, it is difficult to synchronize the cache automatically .

The above cache configuration test is only for performance analysis , There's no usability case , because myBatis If you configure the cache directly , Dirty data may appear ,.

In the case of associated query data ,hiberntae It's a better solution to load lazily with L2 cache ( No dirty data ), Also with myBatis Compared with the obvious advantages . In this situation , Performance and myBatis flat .

In the real world ,myBatis Caching may not be configured on this site , There will be dirty data , So it's very likely that hibernate Performance will be better .

Recent hot article recommends :

1.1,000+ Avenue Java Arrangement of interview questions and answers (2021 The latest version )

2. Don't fill the screen again if/ else 了 , Try strategy mode , It's delicious !!

3. Oh my god !Java Medium xx ≠ null What is the new grammar ?

4.Spring Boot 2.5 Blockbuster released , Dark mode is too explosive !

5.《Java Development Manual ( Song Mountain version )》 The latest release , Download it quickly !

I think it's good , Don't forget to like it + Forward !

版权声明
本文为[Java technology stack]所创,转载请带上原文链接,感谢
https://javamana.com/2021/09/20210909112445626n.html

  1. Java 16 is coming online. You can't even use the features of Java 8, can you?
  2. Java (3) basic data types and their type conversion
  3. 一位Java大牛的BAT面试心得与经验总结,2021年Java春招面试经历,
  4. 一举拿下腾讯美团滴滴offer,快来瞧瞧这份Spring面试小抄!
  5. 一个Java应届生从上海离职,万字长文总结Java多进程,
  6. Seven design principles of java object-oriented design pattern
  7. 一個Java應届生從上海離職,萬字長文總結Java多進程,
  8. Un nouvel étudiant Java a quitté Shanghai et a résumé plusieurs processus Java.
  9. Prenez d'un coup l'offre de Tencent meituan et jetez un coup d'oeil à cette copie de l'entrevue de printemps!
  10. L'expérience et l'expérience d'un Maverick Java en matière d'entrevue sur les MTD, l'expérience de l'entrevue d'embauche du printemps Java en 2021,
  11. Interface graphique X: mise à jour des tables de rendu et optimisation du Code (compilation intégrée 10)
  12. Widget de vérification de fichiers personnalisés Linux
  13. Java thread pool - work queue
  14. [Part 7] - Summary of B2B2C e-commerce technology of spring cloud live mall managed by git branch
  15. Reflection type of Java Foundation
  16. Want to get started with data structures, but always fall under the pomegranate skirt of the linked list?
  17. Interviewer: do redis transactions satisfy atomicity?
  18. 一篇文章教你搞定计算机网络面试,350道Java面试真题分享,
  19. 一条正确的Java职业生涯规划,揭秘今年Java春招面试必问问题有哪些?
  20. 一名毕业三年的女程序媛面试头条经验,关于Redis主从节点数据过期一致性的思考,
  21. Huawei cloud guassdb (for redis) released a new version: Lua script and SSL connection encryption
  22. Java thread pool - work queue
  23. 一名畢業三年的女程序媛面試頭條經驗,關於Redis主從節點數據過期一致性的思考,
  24. Trois ans d'expérience d'entrevue avec une femme de programmation diplômée, une réflexion sur la cohérence de l'expiration des données de redis Master slave Node,
  25. Un plan de carrière Java correct, découvrez les questions que vous devez poser lors de l'entrevue d'embauche du printemps Java de cette année.
  26. 万字详解微服务的哨兵机制,架构师带你玩转Redis高性能缓存设计实战,
  27. Un article vous a appris à gérer les entrevues sur le Web, à partager 350 vraies questions d'entrevue Java,
  28. Jquery Tools Methodology collation, Sharing a little interview Experience
  29. Tutoriel de développement Java, compétences de base nécessaires pour interviewer un programmeur Java dans une grande usine,
  30. "Anti Mafia storm" has just finished, another criminal investigation play has come, and the supporting actor is more popular than the protagonist
  31. 萬字詳解微服務的哨兵機制,架構師帶你玩轉Redis高性能緩存設計實戰,
  32. L'architecte vous guidera dans la conception de cache haute performance de redis.
  33. Linux驱动开发: 杂项字符设备
  34. Jquery plug - in urianchor, app front end Development
  35. Linux驅動開發: 雜項字符設備
  36. Développement de pilotes Linux: périphériques de caractères divers
  37. Utilisez @ async dans Spring boot pour effectuer des appels asynchrones et accélérer l'exécution des tâches!
  38. $in jquery, Visualized Web Development Tool
  39. Le développement Java doit être fait. Les entrevues https demandent souvent une analyse complète.
  40. 不明白JVM虚拟机还怎么面试,一起刷完了这份1307页的Java面试宝典吧,
  41. 不断提升自己创造溢价的能力,字节跳动 阿里 华为 腾讯等大厂Java面试题,
  42. Jdk's Past Life: The Classic Features of Thin Number - java5 - - - 15 -, webfront Development
  43. Résumé des questions d'entrevue pour les ingénieurs en développement Java, analyse des questions d'entrevue à haute fréquence Dubbo,
  44. Améliorer continuellement leur capacité à créer des primes, et les questions d'entrevue Java d'Alibaba Huawei Tencent et d'autres grandes usines sont sautées en octets.
  45. Install docker YJ version of openSUSE 11.3
  46. Je ne comprends pas comment la machine virtuelle JVM peut encore interviewer, et j'ai terminé ce dictionnaire d'entrevue Java de 1307 pages.
  47. 中软国际Java机试,如何写出高效率的SQL?
  48. 中级Java工程师面试,阿里 头条 腾讯等大厂Java笔试题目分享,
  49. 两年Java开发经验,为什么spring能最好地改变Java?
  50. Echarts realizes the rotation of the moon (super simple, you can see it at a glance)
  51. Deux ans d'expérience dans le développement de Java, pourquoi Spring peut - il le mieux changer Java?
  52. Entretien d'ingénieur Java intermédiaire, partage de sujets d'examen écrit Java de grandes usines comme Alibaba headline Tencent,
  53. Zhongsoft International Java Machine test, comment écrire un SQL efficace?
  54. Reflection type of Java Foundation
  55. Comment gérer efficacement les changements dans les ressources k8s?Analyse du mécanisme de mise en œuvre de k8s informer
  56. Installation de jdk1.8
  57. MySQL column - Linux underlying interaction and RAID storage architecture
  58. Interviewer: do redis transactions satisfy atomicity?
  59. 兩年Java開發經驗,為什麼spring能最好地改變Java?
  60. Migration practice from zookeeper to Nacos