Mysql中使用流式查詢避免資料量過大導致OOM

weixin_34054866發表於2018-11-08

點選上方關注,每天學習一個java知識點

一、前言

MySQL 是目前使用比較廣泛的關係型資料庫,而從資料庫裡面根據條件查詢資料到記憶體的情況想必大家在日常專案實踐中都有使用。

當指定條件的資料量特別大時候一般是通過分頁的方式在前端頁面通過 Tag 標籤一頁頁的載入資料到記憶體;但是有些情況下卻不需要使用者切換 Tag 標籤的方式一頁頁的載入資料,這時候如果一下子全部把資料載入記憶體,就有可能會導致 OOM,雖然這時候可以通過程式控制分頁查詢,但是每次查詢時候資料庫都需要把所有符合條件的資料查詢出來然後根據當前頁的返回來返回指定的頁,這無疑加重了 MySQL 伺服器不必要的開銷。

其實在 MySQL 中提供了流式查詢,這允許把符合條件的資料一部分一部分的載入到記憶體,本 Chat 就來具體講解如何在 MySQL中使用流式查詢:

使用流式查詢前,我們是如何在 MySQL 中進行查詢資料的,整個過程發生了什麼?

如何使用 JDBC 程式設計方式在 MySQL 中使用流式查詢?

二、普通查詢

Mysql中使用流式查詢避免資料量過大導致OOM

- 當我們在JVM程式裡面的某一個執行緒裡面執行資料庫查詢時候,其實這個請求首先會呼叫mysql驅動程式。

- mysql驅動接受到請求後會向MySQL伺服器發起TCP請求,伺服器端根據條件查詢出匹配的資料,然後通過TCP連結傳送到MySQL驅動

- MySQL驅動內則會把符合條件的資料快取到驅動內,等伺服器返回了所有符合條件的資料後,在一下子把快取裡面的資料返回給呼叫sql的應用程式。

所以如果查詢的資料量特別大,那麼mysql驅動內快取就可能把記憶體撐爆造成OOM。

三、JDBC程式設計中MySQL流式查詢

mysql客戶端流式查詢不會一下子把伺服器端所有資料快取起來,而是一部分一部分的把伺服器端返回的資料返回給應用程式層,所以可以有效避免OOM。

之前查詢

Mysql中使用流式查詢避免資料量過大導致OOM

Mysql中使用流式查詢避免資料量過大導致OOM

現在流式查詢

Mysql中使用流式查詢避免資料量過大導致OOM

Mysql中使用流式查詢避免資料量過大導致OOM

可知只是prepareStatement時候改變了引數,並且設定了PreparedStatement的fetchsize為Integer.MIN_VALUE。

結果對比

對於同一個sqlCmd,同一批資料,使用兩種方式佔用記憶體對比如下:

  • 非流式程式設計
Mysql中使用流式查詢避免資料量過大導致OOM

  • 流式程式設計
Mysql中使用流式查詢避免資料量過大導致OOM


另外非流式方式由於是把符合條件的資料一下子全部加在到記憶體,並且由於資料量比較大,需要mysql處理的時間比較長,我測試情況下需要一分鐘才會返回結果到記憶體(資料量比較大),然後才能通過資料集返回資料。

而流式方式是每次返回一個記錄到記憶體,所以佔用記憶體開銷比較小,並且呼叫後會馬上可以訪問資料集的資料。

作者:阿里加多

連結:https://www.jianshu.com/p/c1e6eeb71c74

相關文章