【问题标题】:Read large file (Java Heap Space)读取大文件(Java 堆空间)
【发布时间】:2016-10-03 14:50:36
【问题描述】:

我想读取 CSV 文件,从每一行创建对象,然后将这些对象保存到数据库中。 当我从文件中读取所有行并将所有对象存储在 ArrayList 中时,我得到 Java 堆空间错误。 我尝试在读取后立即保存每条记录,但是通过 Hibernate 方法 save() 保存记录需要很多时间。

我还尝试检查我的 arrayList 的大小并在此大小等于 100k 时保存数据(代码的注释部分)。

问题:有什么方法可以部分读取文件,还是有更好的方式在 Java 中存储数据?

String[] colNames;
String[] values;
String line;
Map<Object1, Object1> newObject1Objects = new HashMap<Object1, Object1>();
Map<Object1, Integer> objIdMap = objDao.createObjIdMap();

    StringBuilder raportBuilder = new StringBuilder();
    Long lineCounter = 1L;
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                new FileInputStream(filename), "UTF-8"));
        colNames = reader.readLine().split(";");
        int columnLength = colNames.length;

        while ((line = reader.readLine()) != null) {
            lineCounter++;
            line = line.replace("\"", "").replace("=", "");
            values = line.split(";", columnLength);

            // Object1
            Object1 object1 = createObject1Object(values);
            if (objIdMap.containsKey(object1)) {
                object1.setObjId(objIdMap.get(object1));
            } else if (newObject1Objects.containsKey(object1)) {
                object1 = newObject1Objects.get(object1);
            } else {
                newObject1Objects.put(object1, object1);
            }

            // ==============================================
            // Object2
            Object2 object2 = createObject2Object(values, object1,
                    lineCounter, raportBuilder);
            listOfObject2.add(object2);
            /*
            logger.error("listOfObject2.size():"+listOfObject2.size());
            if(listOfObject2.size() % 100000 == 0){
                object2Dao.performImportOperation(listOfObject2);
                listOfObject2.clear();
            }
            */
        }
        object2Dao.performImportOperation(listOfObject2);

【问题讨论】:

  • 也许使用 0-50 个对象的缓冲区,然后在一次查询中将其保存到数据库中? (我不熟悉hibernate,但很可能这是可能的)这一切都是为了找到正确的缓冲区大小,也许编写一个接受int缓冲区并动态使用它的方法。然后根据您的使用情况,您可以使用不同的缓冲区大小并找到最佳的缓冲区。由于每台计算机的 RAM 都是可变的,因此没有固定的理想缓冲区大小来最佳地将数据插入数据库。数据量如此之大,速度绝不会如此
  • 您使用的是哪个服务器?您需要增加最大堆大小。

标签: java hibernate bufferedreader heap-memory


【解决方案1】:

如果您想处理非常大的文件,增加最大堆大小对您没有帮助。你的朋友是batching

Hibernate 没有隐式使用 JDBC 批处理,并且每个 INSERT 和 UPDATE 语句都是单独执行的。阅读"How do you enable batch inserts in hibernate?" 以获取有关如何启用它的信息。

注意身份生成器,如it disables batch fetching

【讨论】:

    猜你喜欢
    • 2015-06-21
    • 2013-06-28
    • 2015-02-22
    • 2013-11-27
    • 2013-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    相关资源
    最近更新 更多