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