Mysql批量大資料獲取

悠遊0902發表於2019-03-07

背景

mysql連線資料庫的時候,需要從表中拖資料,如果資料量過大會導致服務記憶體溢位。會提示java.lang.OutOfMemoryError: Java heap space錯誤。

解決方案1

嘗試1

使用setFetchSize(1000)指定獲取介面大小

    ps=conn.con.prepareStatement("select * from bigTable");
    ps.setFetchSize(1000);
複製程式碼

事實上,這種指定的方法是沒有任何效果的,伺服器還是會一次性取出所有資料放在客戶端記憶體中,此時setFetchSize引數不起作用,當一條SQL返回資料量較大時可能會出現JVM OOM。

嘗試2

使用setFetchSize(Integer.MIN_VALUE)

    ps = connection.prepareStatement("select * from bigTable",
        ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
複製程式碼

此時客戶端會逐個從伺服器段獲取資料

改進

事實上,setFetchSize(1000)也可以生效的,需要使用useCursorFetch=true

    conn = DriverManager.getConnection("jdbc:mysql://localhost/?useCursorFetch=true", "user", "s3cr3t");
    stmt = conn.createStatement();
    stmt.setFetchSize(100);
    rs = stmt.executeQuery("SELECT * FROM your_table_here");
複製程式碼

摘自:https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-implementation-notes.html

解決方案2

通過指定limit/offset,分頁讀取,這裡不再詳細敘述。

但是該方法會有一個潛在的問題,如讀取重複資料、髒資料,除非在讀取之前LOCK表,讀取完成後 UNLOCK 表 看到網上的解決方案, 可以通過建立一個臨時表解決

  CREATE TEMPORARY TABLE AS SELECT..., and read with LIMIT/OFFSET
複製程式碼

事實上也並不是很好,最好還是通過這種遊標取資料。

相關文章