1. 程式人生 > >MySQL中流式查詢使用

MySQL中流式查詢使用

一、前言

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

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

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

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

二、普通查詢

image.png
  • 當我們在JVM程序裡面的某一個執行緒裡面執行資料庫查詢時候,其實這個請求首先會呼叫mysql驅動程式。
  • mysql驅動接受到請求後會向MySQL伺服器發起TCP請求,伺服器端根據條件查詢出匹配的資料,然後通過TCP連結傳送到MySQL驅動
  • MySQL驅動內則會把符合條件的資料快取到驅動內,等伺服器返回了所有符合條件的資料後,在一下子把快取裡面的資料返回給呼叫sql的應用程式。

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

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

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

JDBC程式設計中MYSQL流式查詢例子:

public void selectData(String sqlCmd,) throws SQLException {

    validate(sqlCmd);

    Connection conn = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;

    try
{ conn = petadataSource.getConnection(); stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE); rs = stmt.executeQuery(); try { while(rs.next()){ try { System.out.println("one:" + rs.getString(1) + "two:" + rs.getString(2) + "thrid:" + rs.getString(3)); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } finally { close(stmt, rs, conn); } }

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

四、最後

上面我們講解了JDBC中流式查詢使用,那麼如下在Mybatis中使用那?

  • 如何在 Mybatis 中使用 MyBatisCursorItemReader 進行流式查詢?
  • 如何在 Mybatis 中使用 ResultHandler 進行流式查詢?
  • 什麼是客戶端流式查詢和伺服器端流式查詢?
    更多流式查詢請單擊 單擊我


加多

加多

高階 Java 攻城獅 at 阿里巴巴加多,目前就職於阿里巴巴,熱衷併發程式設計、ClassLoader,Spring等開源框架,分散式RPC框架dubbo,springcloud等;愛好音樂,運動。微信公眾號:技術原始積累。知識星球賬號:技術原始積累