診斷Java代碼中常見的數據庫性能熱點問題(2)

發表于:2016-05-04來源:infoq作者:Andreas Grabner and點擊數: 標簽:數據庫
診斷糟糕的數據庫訪問模式 在對應用程序進行問題診斷時,我通??傄獧z查幾個數據庫訪問模式。我會逐個分析應用的請求,并將這些問題分別放入以下

  診斷糟糕的數據庫訪問模式

  在對應用程序進行問題診斷時,我通??傄獧z查幾個數據庫訪問模式。我會逐個分析應用的請求,并將這些問題分別放入以下這個“DB問題模式”的分類表中:

  過多的SQL執行(Excessive SQLs):執行大量(大于500)不同的SQL語句

  N+1次查詢問題(N+1 Query):多次(大于20)執行相同的SQL語句

  單一SQL語句執行緩慢(Slow Single SQL):某個單一的SQL語句執行時間占據了響應時間的80%以上

  數據驅動問題(Data-Driven):同樣的請求,由于輸入參數的不同,會執行不同的SQL語句

  數據庫繁忙(Database Heavy):數據庫執行的總體時間占據總體響應時間的60%以上

  未經預處理的語句(Unprepared Statements):在執行相同的SQL時未對語句進行預處理

  連接池資源用光(Pool Exhaustion):由于連接獲取時間過長所導致(getConnection的時間超過了executeStatement)

  低效的連接池訪問(Inefficient Pool Access):對連接池的訪問次數過多(對getConnection的調用超過了executeStatement調用次數的50%)

  數據庫服務服務器超負荷(Overloaded Database Server):來自各個應用的請求過多,造成了數據庫服務器超負荷

  示例1:自主設計的O/R映射器產生了過多的SQL

  我的第一個示例是一個web應用程序,它能夠提供某幢大樓中的會議室信息。會議室的信息都保存在某個數據庫中,每次當用戶生成會議室信息的報表時,就會調用某個自定義的數據訪問層以訪問該數據庫。

  在對個別請求進行分析時,我總是從所謂的事務流(Transaction Flow)著手檢查。事務流是一種可視化選項,可展現出應用程序處理請求的過程。對于會議室信息報表這個請求來說,可以看到,該請求首先進入web服務器層(圖左)、隨后進入應用服務層(圖中),然后對數據層發起調用(圖右)。這些層之間的“鏈接”表現了這些層之間的交互次數,例如這個單一的請求執行了多少次SQL查詢。

  從這個屏幕上我們可以立即發現造成問題的頭兩種模式,即過多的SQL執行模式以及數據庫繁忙模式。讓我們來分析一下:

  (點擊放大圖像)

  很容易就可以看出這個請求產生了大量的SQL語句執行,并且造成數據庫繁忙效應:它總共執行了24889次SQL!花費了40.27秒(占整個請求時間的66.51%)才完成整個執行過程!

  如果我們對個別的SQL語句進行分析,將發現這個請求還有另外的問題,即N+1 次查詢問題以及低效的連接池訪問(下文將進行詳細討論):

  (點擊放大圖像)

  這種糟糕的訪問模式是無法通過對數據庫的索引進行優化而解決的。

  我已經無數次看到這種問題發生了。應用的邏輯需要對某個對象列表進行迭代,但它并沒有選擇使用“貪婪加載”(Eager Loading)方式,則是使用了“延遲加載”(Lazy Loading)方式。這種選擇可能來自于O/R映射框架,例如Hibernate或Spring,也可能來自于自主開發的框架,正如上文所述的示例一樣。該示例使用了某種自主開發的實現方式,它會加載每個會議室對象,并通過獨立的SQL查詢語句獲取每個會議室的全部屬性。每個SQL查詢都是在一個向連接池獲取的JDBC連接中執行的,然后在每個查詢完成之后都會返回。這也解釋了為什么該請求會產生12444次set clientname操作,因為Sybase JDBC驅動每次向連接池請求連接時都會提交這一請求。這就是問題所在!其他的JDBC驅動未必會產生set clientname這個調用,你可以查看一下調用getConnection的次數,這同樣可反映出這個問題。

  對于N+1次查詢問題本身來說,使用連接查詢就可以輕易地避免這一問題。在這個會議室與屬性的示例中,可以使用以下連接查詢:

  select r.*, p.*

  from meeting_rooms as r

  inner join room_properties as p on p.room_id = r.room_id

  結果就是整個執行過程只產生了1次查詢執行,不再是12000多次了!同時也免除了12000次連接的獲取操作以及對“set clientname”的調用。

原文轉自:http://www.infoq.com/cn/articles/Diagnosing-Common-Java-Database-Performance-Hotspots

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97