java - 如何将 1 亿行加载到内存中

标签 java sql jdbc out-of-memory

我需要将 1 亿多行数据从 MySQL 数据库加载到内存中。我的 Java 程序因 java.lang.OutOfMemoryError: Java heap space 而失败 我的机器有 8GB RAM,我在 JVM 选项中给出了 -Xmx6144m。

这是我的代码

public List<Record> loadTrainingDataSet() {

    ArrayList<Record> records = new ArrayList<Record>();
    try {
        Statement s = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
        s.executeQuery("SELECT movie_id,customer_id,rating FROM ratings");
        ResultSet rs = s.getResultSet();
        int count = 0;
        while (rs.next()) {

知道如何解决这个问题吗?


更新

我遇到了 this post ,以及基于下面的评论,我更新了我的代码。看来我能够以相同的 -Xmx6144m 数量将数据加载到内存中,但这需要很长时间。

这是我的代码。

...
import org.apache.mahout.math.SparseMatrix;
...

@Override
public SparseMatrix loadTrainingDataSet() {
    long t1 = System.currentTimeMillis();
    SparseMatrix ratings = new SparseMatrix(NUM_ROWS,NUM_COLS);
    int REC_START = 0;
    int REC_END = 0;

    try {
        for (int i = 1; i <= 101; i++) {
            long t11 = System.currentTimeMillis();
            REC_END = 1000000 * i;
            Statement s = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                    java.sql.ResultSet.CONCUR_READ_ONLY);
            s.setFetchSize(Integer.MIN_VALUE);
            ResultSet rs = s.executeQuery("SELECT movie_id,customer_id,rating FROM ratings LIMIT " + REC_START + "," + REC_END);//100480507
            while (rs.next()) {
                int movieId = rs.getInt("movie_id");
                int customerId = rs.getInt("customer_id");
                byte rating = (byte) rs.getInt("rating");
                ratings.set(customerId,movieId,rating);
            }
            long t22 = System.currentTimeMillis();
            System.out.println("Round " + i + " completed " + (t22 - t11) / 1000 + " seconds");
            rs.close();
            s.close();
        }

    } catch (Exception e) {
        System.err.println("Cannot connect to database server " + e);
    } finally {
        if (conn != null) {
            try {
                conn.close();
                System.out.println("Database connection terminated");
            } catch (Exception e) { /* ignore close errors */ }
        }
    }
    long t2 = System.currentTimeMillis();
    System.out.println(" Took " + (t2 - t1) / 1000 + " seconds");
    return ratings;
}

加载前 100,000 行需要 2 秒。加载第 29 个 100,000 行需要 46 秒。我在中间停止了这个过程,因为它花费了太多时间。这些时间是可以接受的吗?有没有办法提高这段代码的性能? 我在 8GB RAM 64 位 Windows 机器上运行它。

最佳答案

一亿条记录意味着每条记录可能最多占用 50 个字节以适应 6 GB + 一些用于其他分配的额外空间。在 Java 中,50 个字节不算什么;仅仅 Object[] 每个元素占用 32 个字节。您必须找到一种方法来立即在 while (rs.next()) 循环中使用结果,而不是完整保留它们。

关于java - 如何将 1 亿行加载到内存中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14535846/

相关文章:

java和nlp提取信息(恶意软件名称)和过滤

Java sql 插入 JOptionpane

java - 如何保护 Class.forName("com.mysql.jdbc.Driver)?

java - 仅为 mysql jdbc 设置自定义 SSL 信任库

Java HttpURLConnection获取所有内容包括css、img等

java - 将不规则二维数组中的子数组设为 Null

java - 无法将按钮置于右中位置

sql - 复制具有主从关系的多条记录

php - 如果 MySQL 连接或数据库的链接有错误,则打印

sql - CASE WHEN NOT 没有产生正确的结果?