您好,登錄后才能下訂單哦!
Java持久性技巧有哪些,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
一個(gè)高性能的數(shù)據(jù)訪問層需要大量關(guān)于數(shù)據(jù)庫內(nèi)部、JDBC、JPA、Hibernate的知識(shí),下面總結(jié)了一些可用來優(yōu)化企業(yè)應(yīng)用程序的重要的技術(shù)。
1. SQL語句日志
如果您用了生成符合自己使用習(xí)慣的語句的框架,則應(yīng)始終驗(yàn)證每個(gè)語句的有效性和效率。測試時(shí)使用斷言機(jī)制驗(yàn)證更好,因?yàn)榧词乖谔峤淮a之前,也可以捕獲N + 1個(gè)查詢問題。
數(shù)據(jù)庫的連接開銷非常大,因此您應(yīng)該始終使用連接池機(jī)制。
由于連接數(shù)由底層數(shù)據(jù)庫集群的功能給出,所以您需要盡可能快地釋放連接。
在性能調(diào)優(yōu)中,你總是要測量、設(shè)置出正確的連接池,池的大小又是差不多的。 但像FlexyPool這樣工具可以幫助您找到合適的大小,即使您已經(jīng)將應(yīng)用程序部署到生產(chǎn)環(huán)境中。
JDBC批處理允許我們在單個(gè)數(shù)據(jù)庫往返中發(fā)送多個(gè)SQL語句。性能增益在驅(qū)動(dòng)程序和數(shù)據(jù)庫端都很重要。PreparedStatements 非常適合批處理,而某些數(shù)據(jù)庫系統(tǒng)(例如 Oracle)僅支持用于預(yù)處理語句的批處理。
由于JDBC為批處理定義了獨(dú)特的API(例如PreparedStatement.addBatch和PreparedStatement.executeBatch),如果您手動(dòng)生成語句,那么您應(yīng)該從一開始就知道是否應(yīng)該使用批處理。 使用Hibernate,您可以切換到使用單個(gè)配置的批處理。
Hibernate 5.2 提供了會(huì)話級(jí)別的批處理,所以在這方面更加靈活。
語句緩存是您可以輕松利用的最鮮為人知的性能優(yōu)化之一。 根據(jù)基礎(chǔ)的JDBC驅(qū)動(dòng)程序,可以在客戶端(驅(qū)動(dòng)程序)或數(shù)據(jù)庫端(語法樹甚至執(zhí)行計(jì)劃)上緩存PreparedStatements。
當(dāng)使用Hibernate時(shí),IDENTITY生成器不是一個(gè)好的選擇,因?yàn)樗昧薐DBC批處理。
TABLE生成器更糟糕,因?yàn)樗褂靡粋€(gè)單獨(dú)的事務(wù)來獲取新的標(biāo)識(shí)符,這會(huì)對(duì)底層事務(wù)日志以及連接池造成壓力,因?yàn)槊看挝覀冃枰粋€(gè)新的標(biāo)識(shí)符時(shí)都需要單獨(dú)的連接。
SEQUENCE是正確的選擇,甚至從2012版本就開始支持SQL Server。對(duì)于SEQUENCE標(biāo)識(shí)符,Hibernate一直提供優(yōu)化器,如 pooled 或 pooled-lo,這可以減少獲取新的實(shí)體標(biāo)識(shí)符值所需的數(shù)據(jù)庫往返次數(shù)。
您應(yīng)該始終在數(shù)據(jù)庫端使用正確的列類型。 列類型越緊湊,數(shù)據(jù)庫工作集中可容納的條目越多,索引將更好地適應(yīng)于內(nèi)存。 為此,您應(yīng)該利用特定于數(shù)據(jù)庫的類型(例如PostgreSQL中的IPv4地址的inet),尤其是在實(shí)現(xiàn)新自定義類型時(shí),Hibernate非常靈活。
Hibernate 帶有許多關(guān)系映射類型,但并不是所有的關(guān)系映射類型在效率上都是相等的。
應(yīng)該避免單向集合和 @ManyToMany 列表。如果您確實(shí)需要使用實(shí)體集合,則首選雙向 @OneToMany關(guān)聯(lián)。對(duì)于 @ManyToMany 關(guān)系,使用 Set(s),因?yàn)樵谶@種情況下它們更高效,或者簡單地映射鏈接的多對(duì)多表,并將 @ManyToMany 關(guān)系轉(zhuǎn)換為兩個(gè)雙向的 @OneToMany 關(guān)聯(lián)。
然而,與查詢不同,集合不夠靈活,因?yàn)樗鼈儾灰追猪?,這意味著當(dāng)子關(guān)聯(lián)的數(shù)量相當(dāng)高時(shí),我們不能使用它們。出于這個(gè)原因,你應(yīng)該考慮一個(gè)集合是否真的有必要。 在許多情況下,實(shí)體查詢可能是更好的選擇。
就繼承而言,面向?qū)ο笳Z言和關(guān)系數(shù)據(jù)庫之間的不匹配變得更加明顯。 JPA提供了SINGLE_TABLE,JOINED和TABLE_PER_CLASS來處理繼承映射,每個(gè)策略都有其優(yōu)缺點(diǎn)。
SINGLE_TABLE在SQL語句方面表現(xiàn)最好,但由于我們不能使用NOT NULL約束,所以我們在數(shù)據(jù)完整性方面失敗了。
當(dāng)同時(shí)提供更復(fù)雜的語句時(shí),JOINED采用數(shù)據(jù)完整性限制。 只要你不使用基本類型的多態(tài)查詢或@OneToMany關(guān)聯(lián),這個(gè)策略就沒有問題。 它的真正的作用在于對(duì)數(shù)據(jù)訪問層上由策略模式支持的多態(tài)@ManyToOne關(guān)聯(lián)。
應(yīng)該避免使用TABLE_PER_CLASS,因?yàn)樗粫?huì)生成有效的SQL語句。
在使用 JPA 和 Hibernate 時(shí),應(yīng)該始終關(guān)注持久性上下文的大小。 出于這個(gè)原因,您不應(yīng)該過多地使用托管實(shí)體。 通過限制托管實(shí)體的數(shù)量,我們可以獲得更好的內(nèi)存管理,并且默認(rèn)的檢查機(jī)制也將更加高效。
獲取太多的數(shù)據(jù)可能是導(dǎo)致數(shù)據(jù)訪問層性能出問題的首要原因。 一個(gè)問題是,即使是只讀的 Projections,實(shí)體查詢也是專用的。
DTO projections更適合于獲取自定義視圖,而實(shí)體只能在業(yè)務(wù)流需要修改時(shí)才能獲取。
EAGER抓取是最糟糕的,您應(yīng)該避免反模式(Anti-Pattern),例如 Open-Session in View。
關(guān)系數(shù)據(jù)庫系統(tǒng)使用許多內(nèi)存緩沖區(qū)結(jié)構(gòu)來避免磁盤訪問。 數(shù)據(jù)庫緩存經(jīng)常被忽視。 我們可以通過適當(dāng)調(diào)整數(shù)據(jù)庫引擎來顯著降低響應(yīng)時(shí)間,以便工作集駐留在內(nèi)存中,而不是一直從磁盤中獲取。
應(yīng)用程序級(jí)緩存對(duì)于許多企業(yè)應(yīng)用程序來說是不可選的。 應(yīng)用程序級(jí)緩存可以減少響應(yīng)時(shí)間,同時(shí)為數(shù)據(jù)庫關(guān)閉以進(jìn)行維護(hù)或由于某些嚴(yán)重系統(tǒng)故障提供只讀輔助存儲(chǔ)庫。
二級(jí)緩存對(duì)于減少讀寫事務(wù)響應(yīng)時(shí)間非常有用,特別是在主從復(fù)制體系結(jié)構(gòu)中。 根據(jù)應(yīng)用程序的要求,Hibernate允許你在READ_ONLY,NONSTRICT_READ_WRITE,READ_WRITE和TRANSACTIONAL之間進(jìn)行選擇。
在性能和數(shù)據(jù)完整性方面,事務(wù)隔離級(jí)別的選擇是非常重要的。 對(duì)于多請求Web流程,為避免丟失更新,您應(yīng)該對(duì)分離的實(shí)體或 EXTENDED 持久性上下文使用 optimistic 鎖定。
為避免optimistic locking誤報(bào),您可以使用無版本 optimistic 并發(fā)控制或基于讀寫的屬性集來拆分實(shí)體。
僅僅因?yàn)槟褂肑PA或Hibernate,并不意味著您不應(yīng)該使用原生查詢。 您應(yīng)該利用窗口函數(shù),CTE(公用表表達(dá)式),CONNECT BY,PIVOT 查詢。
這些構(gòu)造允許您避免獲取太多的數(shù)據(jù),以便稍后在應(yīng)用程序?qū)舆M(jìn)行轉(zhuǎn)換。 如果可以讓數(shù)據(jù)庫進(jìn)行處理,那么只能獲取最終結(jié)果,因此可以節(jié)省大量的磁盤I / O和網(wǎng)絡(luò)開銷。 為避免主節(jié)點(diǎn)重載,可以使用數(shù)據(jù)庫復(fù)制和擁有多個(gè)從屬節(jié)點(diǎn),這樣數(shù)據(jù)密集型的任務(wù)就會(huì)在從屬節(jié)點(diǎn)而不是主節(jié)點(diǎn)上執(zhí)行。
關(guān)系數(shù)據(jù)庫的伸縮性非常好。如果Facebook、Twitter、Pinterest或StackOverflow可以擴(kuò)展他們的數(shù)據(jù)庫系統(tǒng),那么很有可能您可以將企業(yè)應(yīng)用程序擴(kuò)展到其特定的業(yè)務(wù)需求。
數(shù)據(jù)庫復(fù)制和分片是提高吞吐量的很好的方法,您應(yīng)該完全可以利用這些經(jīng)過測試的架構(gòu)模式來擴(kuò)展您的企業(yè)應(yīng)用程序。
高性能數(shù)據(jù)訪問層必須與底層數(shù)據(jù)庫系統(tǒng)互相響應(yīng)。 了解關(guān)系數(shù)據(jù)庫和正在使用的數(shù)據(jù)訪問框架的內(nèi)部工作原理可以使企業(yè)高性能應(yīng)用程序和幾乎沒有crawls的應(yīng)用程序之間產(chǎn)生差異。
看完上述內(nèi)容,你們掌握J(rèn)ava持久性技巧有哪些的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。