当前位置: 首页 > 面试题库 >

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

龙德义
2023-03-14
问题内容

我需要将一个MySQL数据库中的1亿多行记录加载到内存中。我的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()) {

任何想法如何克服这个问题?

更新

我碰到了这篇文章 ,以及根据下面的评论更新了我的代码。看来我能够以相同的-
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())循环中使用结果,而不是完全保留它们。



 类似资料:
  • 在服务器重置缓存数据保存在磁盘存储后。但在服务器启动后不使用缓存数据。所以我想加载磁盘存储内容到memory.How做到这一点?在这个堆栈问题加载EhCache磁盘存储内容到内存中使用BootstrapCacheLoaderFactory但不为我出现。

  • 如EhCache留档所述: 实际上,这意味着持久性内存中缓存将启动,其所有元素都将在磁盘上。[...]因此,Ehcache设计不会在启动时将它们全部加载到内存中,而是根据需要懒惰地加载它们。 我希望内存缓存启动时将所有元素都存储在内存中,我该如何实现? 这是因为我们的网站对缓存执行了大量的访问,所以我们第一次访问网站时,它的响应时间非常长。

  • 问题内容: 我想知道如何将字节数组加载到 内存 URLClassLoader中?字节数组是jar文件的解密字节(如下所示)! 大多数内存类加载器都使用ClassLoader而不是URLClassLoader!我需要它使用URLClassLoader。 谢谢! 问题答案: 我将在这里发布我过去做过的实现: 我的自定义ClassLoader:

  • 虽然我有重复问题的风险,但我还没有找到配置的解决方案。 我正在尝试将rJava加载到RStudio中。 我使用的是最新的Mac OS x,Rstudio版本只有几个月的历史,我刚刚安装了JDK x64 12.0.1 rJava的版本是0.9-11 执行时: 我面临着通常的情况: 错误:“rJava”的包或命名空间加载失败:。“rJava”的loadNamespace()中的onLoad失败,详细信

  • 问题内容: 如果已经将整个.class文件序列化为byte [],并假定该类的名称已知(与byte []一起传递),则如何转换byte []-> Class->然后将其加载到JVM,以便以后可以通过调用Class.forName()使用它? 注意: 之所以这样做,是因为我将.class发送到另一台主机,而主机的JVM不知道此.class。 问题答案: 我现在在测试中实际上正在使用类似的方法,将一组