Github系列文章地址html
原文地址java
一個高性能的數據訪問層須要不少關於數據庫的內部結構、JDBC、JPA、Hibernate以及不少優化商業應用的技術建議。git
若是你正在使用譬如Hibernate或者MyBatis這樣的ORM框架,那麼能夠參考驗證執行語句的效率。另外推薦一個 測試中斷言機制 能夠幫你在提交代碼以前就發現不少的查詢問題。github
數據庫鏈接一直是數據庫中比較耗時的操做,所以建議是務必使用數據庫鏈接池 機制。另外,數據庫鏈接還受到數據庫底層的限制,所以也須要合理有效地釋放無用的數據庫鏈接。在性能調優中,咱們常常須要測試而且設置合理的鏈接池大小。這裏推薦一個FlexyPool工具能夠幫助你選擇生產環境下合適的鏈接池大小。sql
JDBC Batching容許在單次數據庫鏈接中發送多個SQL語句。這篇博客裏進行了對比能夠看出Batch操做的性能提高很是巨大 ,不管是在客戶端仍是數據庫端。 PreparedStatements
是不錯的用於Batching操做的選擇,像Oracle也僅支持基於PreparedStatements的Batching操做。數據庫
JDBC中已經基於PreparedStataement.addBatch
與 PreparedStataement.executeBatch
)提供了Batching操做的輔助,不過若是打算手動的構造Batching操做,那麼在設計階段就要考慮到是否須要引入Batching。若是你用的是Hibernate,那麼能夠用簡單的配置就開啓Batching,Hibernate 5.2 提供了 Session級別的Batching, 也是很是方便的。json
Statement Caching算是最不經常使用的幾種優化手段之一了,你能夠利用PreparedStatements
同時在客戶端(Driver)或者數據庫端同時緩存語句。api
若是你是使用Hibernate做爲ORM工具,那麼IDENTITY
生成器可能會影響到你的性能,由於它會禁止掉JDBC Batching。Table
生成器也不是啥好選擇,它會使用獨立的事務上下文進行捕獲操做,而致使底層的事務日誌承受額外的壓力,而且致使了每次鏈接池中的新的請求都須要一個新的Identifier。所以筆者仍是推薦SEQUENCE
生成器,SQL Server在2012版本以後也開始支持了該生成器。緩存
在數據庫設計的時候,咱們應該儘量地選用合適的列類型,這樣可讓你的數據庫以最合適的方式去索引存儲你的數據。譬如在PostgreSQL中你應該使用inet
來存放IPv4的地址,特別是Hibernate還容許你自定義數據類型,這樣方面和數據庫中的列類型一一對應。性能優化
Hibernate提供了不少的關係映射,不過並非全部的映射都是性能優化的。
咱們在開發的過程當中須要注意避免單向的關係映射,以及@ManyToMany
這種映射。對於集合查詢而言,雙向的@OneToMany
關係纔是值得推薦的。
繼承是面向對象的語言中的不可或缺的一部分,但這也是關係型數據庫與面向對象的語言之間的不協調最甚的地方。JPA提供了譬如SINGLE_TABLE
、JOIN
以及TABLE_PER_CLASS
來處理繼承映射的問題,而這幾個辦法都是各有千秋。
SINGLE_TABLE
在SQL語句中的表現最好,不過不能使用NOT NULL
約束,數據完整性的控制較差。
JOIN
經過更復雜的語句控制來保證了數據的完整性,只要你不使用多態查詢或者@OneToMany
關係註解,那一切還好。
應該避免使用TABLE_PER_CLASS
,它基本上沒法生成高效的SQL語句。
在使用JPA或者Hibernate時候,應該隨時注意持久化上下文的大小,避免同時管理過多的實體類。經過限制受管實體類的數量,咱們能夠更好地進行內存管理,而默認的髒檢測機制也會有更好的效果。
獲取過多的冗餘數據多是致使數據訪問層性能降低的緣由之一,即便是包含了投影等操做,對於實體的查詢應該也是排外的,即不會引入冗餘數據的。咱們應該只獲取那些業務邏輯須要到的數據,這裏推薦使用DTO Projections。過早的數據獲取以及Open Session In View這種反模式都是要被避免的。
關係型數據庫使用了不少的內存緩衝結構體來避免大量的磁盤訪問,可是咱們每每忽略了數據庫緩存。咱們能夠經過調整數據庫查詢引擎,將更多的內容留於內存中以免磁盤查詢最終明顯的減小響應耗時。應用層的緩存則利用高速副本的方式來保證低響應時間。而Second-Level緩存可以有效減小讀寫事務的響應時間,特別是在主從複製架構中。根據不一樣的應用取錢,Hibernate提供了 READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, 以及 TRANSACTIONAL這幾種方式。
在考慮性能和數據完整性的時候,事務隔離層 就變得相當重要。對於併發較高的應用,須要避免更新失敗, 可使用 樂觀鎖或者擴展的持久化上下文.
而爲了不 樂觀鎖中的
false positives, 可使用 無版本的樂觀控制或者基於寫屬性集的實體劃分.
雖然你是用了JPA或者Hibernate,可是你能夠用一些原生查詢,建議是好好利用Window Functions, CTE (Common Table Expressions), CONNECT BY
, PIVOT
等等。這些工具可以避免你一次性傳輸過多的數據進入應用層,若是你能夠把這個操做託付給數據庫層進行,那麼能夠僅關心最終的結果,從而節約了磁盤IO與網絡帶寬。
關係型數據庫可以方便地進行擴展,像Facebook、Twitter、Pinterest這些大公司都擴展了數據庫系統:
數據副本與分片是兩種經常使用的增長吞吐量的擴展方式,你應該合理的組合應用這些方式從而提升你的商業應用的能力。