用于以最小内存消耗写入文件的设计模式

时间:2015-01-20 19:30:35

标签: java performance design-patterns out-of-memory file-writing

我需要通过读取xml来编写文件,其中包含要从数据库中提取的格式信息和值。我正在研究大量的记录(200,000)。 我已经尝试将所有数据保存在内存中,但内存错误。 我曾尝试一次又一次地击中数据库,但后来我遇到了性能问题。由于查询被一次又一次地击中会降低性能。

该过程涉及的步骤:

  1. 命中db以获取要创建哪个文件的所有记录
  2. 使用Jaxb
  3. 读取xml文件
  4. 创建从步骤1获得的所有数据的地图。
  5. 迭代从步骤1获得的地图
  6. 从创建的格式对象中导出需要显示的数据 在第2步
  7. 将结果附加到每个记录的字符串中,然后写入相同的内容 到文件
  8. 尽管如此,最后我通过一次读取预定义的数据计数并为此编写文件然后处理下一堆来解决这个问题。但是我没有遵循任何设计模式。

    是否有使用最少内存的设计模式让我有效地写文件?

2 个答案:

答案 0 :(得分:2)

设计模式称为 Pagination (使用游标)。例如,当您向Oracle DB发送查询时,返回的结果集中的默认结果数为50.只有当您要求结果集获取next()时,它才会返回接下来的50个结果。这就是大多数数据库的工作方式和设计对这种模式有效的方式(见code example):

public static void viewTable(Connection con, String dbName)
    throws SQLException {

    Statement stmt = null;
    String query =
        "select COF_NAME, SUP_ID, PRICE, " +
        "SALES, TOTAL " +
        "from " + dbName + ".COFFEES";

    try {
        stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery(query);
        while (rs.next()) {
            String coffeeName = rs.getString("COF_NAME");
            int supplierID = rs.getInt("SUP_ID");
            float price = rs.getFloat("PRICE");
            int sales = rs.getInt("SALES");
            int total = rs.getInt("TOTAL");
            System.out.println(coffeeName + "\t" + supplierID +
                               "\t" + price + "\t" + sales +
                               "\t" + total);
        }
    } catch (SQLException e ) {
        JDBCTutorialUtilities.printSQLException(e);
    } finally {
        if (stmt != null) { stmt.close(); }
    }
}

所以,你可以打开文件,写下你得到的结果的每个“页面”,要求下一页等等。完成后 - 关闭文件。

答案 1 :(得分:0)

如果您正在写XML,我建议您在阅读时写出每条记录。这样您一次只需要一条记录足够的内存,而且您拥有的记录数无关紧要。

e.g。

Statement stmt = null;
String query =
    "select COF_NAME, SUP_ID, PRICE, " +
    "SALES, TOTAL " +
    "from " + dbName + ".COFFEES";

try {
    stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery(query);
    while (rs.next()) {
        xmlFile.println("<coffee>\n" +
              "<coffeename>" + rs.getString("COF_NAME") + "</coffeename>\n" +
              "<supId>" + rs.getInt("SUP_ID")+ "</supId>\n" + 
              "<price>" + rs.getFloat("PRICE") + "</price>\n" + 
              "<sales>" + rs.getInt("SALES") + "</sales>\n" + 
              "<total>" + rs.getInt("TOTAL") + "</total>\n" +
              "</coffee>");
    }
} catch (SQLException e ) {
    JDBCTutorialUtilities.printSQLException(e);
} finally {
    if (stmt != null) { stmt.close(); }
}

如果字符串包含特殊字符,您可能需要转义它们。