Java如何在结果集中检索超过一百万行

时间:2018-06-20 16:51:17

标签: java jdbc

我正在对具有16,213,156行和10列的MYSQL表执行选择查询。但是建立连接后,代码仅执行几分钟,然后抛出错误:线程“ Thread-3”中的异常java.lang.OutOfMemoryError:Java堆空间

我的系统配置是16 gb RAM,Java 8

我尝试将Jvm参数设置为-Xms4G和-Xmx12G。还尝试设置stmt.setFetchSize(); //到10,100,1000仍然相同的错误

我可以使用JDBC API提取这么多的记录吗?任何帮助将不胜感激。

package com;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;

import com.opencsv.CSVWriter;

public class Test1 {
    private static Connection conn = null;

    public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException {

        connection();
        retrieve(conn);

    }



    public static void connection()
    {

        try
        {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "<jdbc connection url>";
            conn = DriverManager.getConnection(url, "<username>", "<password>");
            System.out.println("Connection established");       
        }

        catch(Exception e)
        {
            e.printStackTrace();
        }

    }


    public static void retrieve(Connection conn)
    {
        ResultSet rs = null;
        Statement stmt = null;
        try
        {

            stmt = conn.createStatement();
            //  stmt.setFetchSize(100); // 1000, 10
            System.out.println(stmt.getFetchSize());  // By default prints 0
            rs = stmt.executeQuery("SELECT * FROM tablename");
            CSVWriter writer = new CSVWriter(new BufferedWriter(new FileWriter("C:\\finaldata\\test.csv")));
            System.out.println("**** Started writing Data to CSV ****");
            int lines = writer.writeAll(rs, true, false, false);        
            writer.flush();
            writer.close();
            System.out.println("** OpenCSV -Completed writing the resultSet at " +  new Date() + " Number of lines written to the file " + lines);  

        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

4 个答案:

答案 0 :(得分:1)

@MickMnemonic感谢您的帮助,此问题已得到解决。

仅设置获取大小可能不足以使MySQL驱动程序开始从数据库流式传输数据,而不是立即加载所有内容。您可以尝试使用stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE);

答案 1 :(得分:0)

我遇到了类似的问题,即从MySQL数据库读取几百万行。 我正在阅读一个称为Reader的PreparedStatement。然后在PrepareStatement之后,我将fetchsize减小到最小:

PreparedStatement reader = connection.prepareStatement("select....");
reader.setFetchSize(Integer.MIN_VALUE);

从那时起,我就再也没有遇到过问题。

答案 2 :(得分:0)

限制查询,例如

SELECT * FROM message_history limit {start from row no.} , {no. of rows to select}

示例-

SELECT * FROM message_history limit 100000,200000;

将检索从100000到300000的行; 像这样分成几批。

PreparedStatement statement = con.prepareStatement(query);
statement.setFetchSize(Integer.MIN_VALUE);
rs = statement.executeQuery();

这种方法对我有用,可检索2200万条记录。

答案 3 :(得分:-1)

如果您要进行一些搜索或操作,请尝试在数据库层进行操作,而不是在应用程序层中将其全部获取,然后进行操作/搜索。获取大量记录不是一个好习惯。在该处提供搜索过滤器选项,以便用户可以根据自己的需要过滤记录,因为记录变得越来越繁琐,您需要管理所有这些记录。