数据库
首页 > 数据库> > 使用Java将大量数据从数据库导出到.csv时出现问题

使用Java将大量数据从数据库导出到.csv时出现问题

作者:互联网

我,谢谢您的关注.

我想使用Java将大量数据,实际上是大量数据(600万行)导出到.csv文件.该应用程序是使用toplink(ojdbc14)的JPA摆动应用程序.

我尝试使用:

但是BufferedWriter
RandomAccessFile的
FileChannel

等等,但是尽管我将最大堆大小设置为800m(-Xmx800m),但是内存消耗仍然很高,导致Java堆内存不足异常.

我的源代码的最新版本:

...(more lines of code)

FileChannel channel = getRandomAccessFile(tempFile).getChannel();
Object[][] data = pag.getRawData(); //Database data in a multidimentional array

            for (int j = 0; j < data.length; j++) {
                write(data[j], channel); //write data[j] (an array) into the channel
                freeStringLine(data[j]); //data[j] is an array, this method sets all positions =null
                data[j] = null;//sets reference in null
            }

            channel.force(false); //force writing in file system (HD)
            channel.close(); //Close the channel
            pag = null; 

...(more lines of code)

 private void write(Object[] row, FileChannel channel) throws DatabaseException {
    if (byteBuff == null) {
        byteBuff = ByteBuffer.allocateDirect(1024 * 1024);
    }
    for (int j = 0; j < row.length; j++) {
        if (j < row.length - 1) {
            if (row[j] != null) {
                byteBuff.put(row[j].toString().getBytes());
            }
            byteBuff.put(SPLITER_BYTES);
        } else {
            if (row[j] != null) {
                byteBuff.put(row[j].toString().getBytes());
            }
        }
    }
    byteBuff.put("\n".toString().getBytes());        
    byteBuff.flip();
    try {
        channel.write(byteBuff);
    } catch (IOException ex) {
        throw new DatabaseException("Imposible escribir en archivo temporal de exportación : " + ex.getMessage(), ex.getCause());
    }
    byteBuff.clear();
}

作为600万行,我不想在创建文件时将该数据存储在内存中.我制作了许多临时文件(每个文件有5000行),最后,使用两个FileChannel将所有这些临时文件附加到一个文件中.但是,缺少内存的异常是在加入之前启动的.

您现在是否是导出大量数据的另一种策略?

非常感谢您的答复.对不起,我的英文,我正在提高xD

解决方法:

答案是使用“流”方法-即在滚动数据集时读一行,写一行.您将需要获取查询结果作为游标并对其进行遍历,而不是获取整个结果集.

在JPA中,使用如下代码:

ScrollableResults cursor = session.createQuery("from SomeEntity x").scroll();

while (cursor.next()) {
    writeToFile(cursor);
}

这意味着您一次只能在内存中存储一​​行,这完全可以扩展到任意数量的行,并且使用最少的内存(无论如何它都更快).

一次获取结果集中的所有行是一种便捷的方法,它适用于较小的结果集(通常是大多数时间),但是像往常一样,便捷是有代价的,并且并非在所有情况下都有效.

标签:export-to-csv,java,memory,database
来源: https://codeday.me/bug/20191011/1896402.html