1

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

该过程涉及的步骤:

  1. 点击 db 以获取要为其创建文件的所有记录
  2. 使用 Jaxb 读取 xml 文件
  3. 创建从步骤 1 获得的所有数据的映射。
  4. 迭代从 step1 获得的地图
  5. 从步骤 2 中创建的格式对象导出需要显示的数据
  6. 将结果附加到每个记录的字符串中,然后将其写入文件

不过,最后我通过读取预定义的数据计数并为此写入文件然后处理下一组数据来解决这个问题。但是我没有为此遵循任何设计模式。

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

4

2 回答 2

2

该设计模式称为分页(使用光标)。例如,当您向 Oracle DB 发送查询时,返回的结果集中的默认结果数为 50。只有当您要求结果集获取时next(),才会返回接下来的 50 个结果。这就是大多数 DB 的工作方式,并被设计为对这种模式有效(请参阅此代码示例):

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(); }
    }
}

所以,你可以打开文件,写下你得到的每一“页”结果,请求下一页等等。一旦你完成了——关闭文件。

于 2015-01-20T19:35:01.383 回答
0

如果您正在写入 XML,我建议您在读取时写出每条记录。这样您一次只需要足够的内存来存储一条记录,而您拥有多少条记录并不重要。

例如

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(); }
}

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

于 2015-01-20T19:43:00.723 回答