将大型ResultSet写入文件

Mad*_*dhu 6 java io jdbc

我正在尝试将一个大的ResulSet(~1mm行)写入单个文件.在Java 1.6中有一个首选/有效的方法吗?

Bal*_*usC 13

这取决于使用的JDBC驱动程序.您需要指示JDBC驱动程序不要ResultSet事先将整个加载到Java的内存中,而是在每次next()调用时按行加载它.然后,在ResultSet#next()循环内部,您需要立即将数据写入文件,而不是将其保存在其中List.

目前还不清楚你正在使用什么JDBC驱动程序,但是例如可以根据MySQL JDBC驱动程序文档,按照以下方式指示MySQL JDBC驱动程序以每行为基础提供结果集:

结果集

默认情况下,ResultSet完全检索并存储在内存中.在大多数情况下,这是最有效的操作方式,并且由于MySQL网络协议的设计更容易实现.如果您正在使用具有大量行或大值的ResultSet,并且无法在JVM中为所需内存分配堆空间,则可以告诉驱动程序一次将结果流回一行.

要启用此功能,您需要以下列方式创建Statement实例:

 stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
 stmt.setFetchSize(Integer.MIN_VALUE);
Run Code Online (Sandbox Code Playgroud)

这是一个具体的启动示例:

try (
    PrintWriter writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(new FileOutputStream("/records.txt")), "UTF-8"));
    Connection connection = dataSource.getConnection();
    Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
) {
    statement.setFetchSize(Integer.MIN_VALUE);

    try (ResultSet resultSet = statement.executeQuery("SELECT col1, col2, col3 FROM sometable")) {
        while (resultSet.next()) {
            writer.append(resultSet.getString("col1")).append(",")
                  .append(resultSet.getString("col2")).append(",")
                  .append(resultSet.getString("col3")).println();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我首先检查数据库是否没有内置的SQL支持,这可以更有效地做到这一点.例如,MySQL有一个这样的SELECT INTO OUTFILE结构.

所述SELECT ... INTO OUTFILE 'file_name'的形式SELECT的选择的行写入到一个文件中.该文件是在服务器主机上创建的,因此您必须具有FILE使用此语法的权限.file_name不能是现有文件,除其他外,它可以防止文件/etc/passwd和数据库表被破坏.从MySQL 5.1.6开始,character_set_filesystem系统变量控制文件名的解释.