MySQL 使用 JPA + Hibernate 的 9 個高效能技巧
本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃!
介紹
儘管有SQL標準,但每個關聯式資料庫終將是唯一的,因此你需要調整資料訪問層,以便充分利用在使用中的關聯式資料庫。
在本文中,我們將介紹在使用帶有JPA和Hibernate的MySQL時,為了提高效能,我們可以做哪些事情。
不要使用AUTO識別符號GeneratorType
每個實體都需要識別符號,標識符惟一地標識與該實體關聯的表記錄。JPA和Hibernate允許根據三種不同的策略自動生成實體識別符號:
- IDENTITY
- SEQUENCE
- TABLE
正如我在這篇文章中所解釋的,當增加資料庫連線數時,TABLE識別符號策略不會縮放。而且,即使是一個資料庫連線,識別符號生成響應時間比使用IDENTITY或SEQUENCE大十倍。
如果你使用AUTO GenerationType
:
@Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id;
Hibernate 5將會退回到使用TABLE生成器,這對效能不利。
正如我在這篇文章中所解釋的,你可以使用以下對映輕鬆解決此問題:
@Id @GeneratedValue(strategy= GenerationType.AUTO, generator="native") @GenericGenerator(name = "native", strategy = "native") private Long id;
本地生成器將選擇IDENTITY而不是TABLE。
IDENTITY生成器禁用JDBC批處理插入
MySQL 5.7和8.0都不支援SEQUENCE物件,因此你需要使用IDENTITY。但是,正如我在這篇文章中所解釋的,IDENTITY生成器可以防止Hibernate使用JDBC批量插入。
JDBC批量更新和刪除不受影響,只有INSERT語句不能被批處理,因為在Persistence Context被重新整理之前,INSERT語句已被執行,從而Hibernate知道要分配給持久化實體什麼實體識別符號。
如果要解決此問題,則必須通過不同的框架,如jOOQ,執行JDBC批處理插入。
通過Docker和tmpfs加速整合測試
MySQL和MariaDB在不得不丟棄資料庫模式的時候,以及每次新的整合測試即將執行因而重新建立它的時候,是非常慢的。但是,你可以在Docker和tmpfs的幫助下輕鬆解決此問題。
正如我在這篇文章中所解釋的,通過對映記憶體中的資料資料夾,整合測試的執行速度將與有記憶體資料庫(如H2或HSQLDB)時的速度相同。
對非結構化資料使用JSON
即使是在你使用RDBMS的時候,肯定也有很多次想要儲存非結構化資料:
- 來自客戶端,如JSON的資料,需要被解析並插入到我們的系統中。
- 可以快取的影像處理結果以儲存再處理
雖然本機不支援,但是你可以輕鬆地將Java物件對映到JSON列。甚至可以將JSON列型別對映到Jackson JsonNode。
更重要的是,你甚至不必編寫這些自定義型別,可以從Maven Central中抓取:
<dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-52</artifactId> <version>1.0.0</version> </dependency>
很酷,對吧?
使用儲存過程來儲存資料庫
在處理大量資料時,將所有資料移入和移出資料庫並不是非常高效。不過,通過呼叫儲存過程對資料庫端進行處理會好很多。
有關更多詳細資訊,請參閱這篇有關如何呼叫帶有JPA和Hibernate的MySQL儲存過程的文章。
小心ResultSet流
SQL流在兩層應用程式中是很有意義的。如果你要執行ResultSet流,那麼你也得注意JDBC驅動程式。在MySQL上,你需要將Statement大小設定為Integer.MIN_VALUE。
然而,對於基於Web的應用程式,分頁更為合適。JPA 2.2甚至引入了對Java 1.8 Stream方法的支援,但執行計劃可能不如使用SQL級別分頁時那麼高效。
PreparedStatements可能會被模擬
你可能以為,既然Hibernate預設使用PreparedStatements
,那麼所有語句都是像這樣執行的:
實際上,更像是這樣執行的:
正如我在這篇文章中所解釋的,除非你設定了useServerPrepStmts
MySQL JDBC驅動程式屬性,否則PreparedStatements將在JDBC驅動程式級別進行模擬以儲存一個額外的資料庫。
始終結束資料庫事務
在關聯式資料庫中,每個語句都在給定的資料庫事務中執行。因此,事務是不可選的。
但是,你應該始終通過提交或回滾來結束當前正在執行的事務。忘記結束事務可能會導致持續被鎖很長時間,同時也會阻止MVCC清理過程回收不再需要的舊元組或索引條目。
遞交日期/時間沒有那麼容易
程式設計中有兩件非常複雜的事情:
- 處理編碼
- 處理跨多個時區的日期/時間
為了解決第二個問題,最好在UTC時區中儲存所有時間戳。但是,當使用MySQL時,你還需要將useLegacyDatetimeCode
JDBC Driver配置屬性設定為false
。
結論
正如你所看到的,在使用帶有JPA和Hibernate的MySQL時,要記住許多事情。因為MySQL是最為廣泛部署的RDBMS之一,並被絕大多數的Web應用程式所使用,所以,瞭解所有這些技巧並調整資料訪問層來最大限度地利用它非常有用。
譯文連結:http://www.codeceo.com/article/mysql-jpa-hibernate-9-tips.html
英文原文:9 High-Performance Tips when using MySQL with JPA and Hibernate
翻譯作者:碼農網 – 小峰
[ 轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]
相關文章
- Oracle資料庫與JPA和Hibernate 結合使用時的九個高效能技巧 - vladmihalceaOracle資料庫
- 使用Hibernate、JPA、Lombok遇到的有趣問題Lombok
- 如何使用Hibernate/JPA的JPQL/HQL查詢提取?
- 【SpringBoot Demo】MySQL + JPA + Hibernate + Springboot + Maven DemoSpring BootMySqlMaven
- 如何在SpringBoot中使用Hibernate/JPA的@NaturalId?Spring Boot
- 淺談JPA二:聊聊Hibernate
- JPA/Hibernate/Spring Data概念Spring
- Spring boot 四 JPA HibernateSpring Boot
- websphere 6.1如何將open jpa 切換為hibernate jpaWeb
- 如何透過Hibernate/JPA在MySQL中儲存UTC時區?MySql
- 10個大大提升MySQL效率的使用技巧MySql
- Hibernate annotation, JPA如何對映多個屬性為unique
- 9 個強大的 JavaScript 小技巧JavaScript
- 使用JPA和Hibernate呼叫儲存過程的最佳方法 - Vlad Mihalcea儲存過程
- 如何在Hibernate/JPA的實體和查詢中使用Java 8 Optional?Java
- 14個高效能Java永續性技巧Java
- 9 個 Yoinkmac使用小技巧,提升你的 Mac 文件解決效率Mac
- 如何在Hibernate/JPA中配置具有兩個連線池的兩個資料來源
- Laravel 9 個不經常用的小技巧Laravel
- 在 Spring Boot 中使用 JPA 和 MySQLSpring BootMySql
- JPA和Hibernate的樂觀鎖與悲觀鎖
- yoink for mac版使用圖文教程及9個實用技巧~Mac
- iOS 開發的9個超有用小技巧iOS
- 10個提升MySQL效能的小技巧MySql
- 使用JPA和Hibernate延遲載入實體屬性的最佳方法 - Vlad Mihalcea
- maven springmvc spring data jpa hibernate sqlserver demoMavenSpringMVCSQLServer
- MySQL9的3個新特性MySql
- Web開發中9個有用的提示和技巧Web
- JPA配置mysql連線MySql
- Hibernate/JPA如何保證不生成多餘的SQL語句?SQL
- 多年教訓:根據DDD設計原則改變JPA/Hibernate的使用方式 - lorenzo
- 前端優化:9 個技巧,提高 Web 效能前端優化Web
- 前端優化 9 個技巧,提高 Web 效能前端優化Web
- 提升 iOS 開發效率! Xcode 9 內建模擬器的9個技巧iOSXCode
- mysql 使用技巧 分頁limitMySqlMIT
- 使用Java API的5個技巧JavaAPI
- Spring Data JPA 的使用Spring
- 【前端詞典】提高幸福感的 9 個 CSS 技巧前端CSS