java 结果集 returns 大量数据时出现堆大小问题

java Heap Size Issue when result set returns large number of data

我有一个 java-spring-hibernate 网络应用程序,它调用我的 sql 存储过程,该存储过程调用用户特定的 "event" 信息。

要求是将结果集写入文本文件并将其发送到一个 ftp 服务器。我分配了 space 的 4gb,因为堆 size.I 无法分配更多的堆比这个大。但是当存储过程 return 大结果集并从服务器端处理它时,堆大小问题就会出现

当前代码:

1:存储过程return 大结果集(比如几百万行)

2:将其映射到列表

3:将每一行写入一个文本文件。对于单个用户,只写 3 个事件。如果他有超过 3 个事件,请忽略它(请注意我从 mysql 获取基于电子邮件的排序结果集).这个过程我需要在服务器端做

4:结果集大时出现堆大小问题

伪代码:

 Stored proc
    delete temp table if exist
     get public event  into temp1 table based on condition
     get non public event into temp2 table
     create new temp tabletemp 3 by joining temp1 and temp2 and join with user table with some condition and sort it
    return select * from temp3 sorted based on email

即使设置了所有必需的索引,通常也需要 20 分钟才能完成 服务器端代码

   1:Create File writer object
    2:call stored proc
    import javax.persistence.EntityManager;
    ...
    ..
    Query query = entityManager.createNativeQuery("CALL procName(param)");
    ....
    list = query.getResultList();
    ....
    for (final Object[] objects : evntList) {
                    final EvntDTO dto = new ExactTargetDailyMailDTO(
                            String.valueOf(objects[0]),
                            String.valueOf(objects[1]),....,....,);
    if dto.getEvntNAme() matches some condition(){
    //change event name and other params accordingly
    }
    eventList.add(dto);
    }
    ...
    for (int i = 0; i < eventList.size(); i++) {
    Dto dto = eventList.get(i);
    count=1;
    ...
    fileContent=dto.getEmail()+appendmore user info +dto.getEventInfo();

    while (i + 1 < eventList.size()
                            && dto.getEmail().equalsIgnoreCase(remindersList.get(i + 1).getEmail())) {
                    if (count < 3) {
                    ....
                   fileContent=fileContent+add next EventInfo 

                   }
    ...
    ..
                   bw.write(fileContent);
                    bw.newLine();

    }
bw.close();
fw.close();

任何人都可以建议我一个更好的计划吗?

因为我想在这个列表中做一些更多的操作(比如如果他有超过 3 个事件忽略它),我不能想到一次获取 1000 或 100 000 个数据并将其写入文件并重复进程

谁能建议我更好的架构和实现方式?

跳过第2步:存入列表。

这样你就可以将所有流式结果集强制到内存中。

如果你在sql之前打开文件,然后为每个rs.next写一行() 您一次只能在内存中存储一​​些行。

如果超过 3 个事件在删除后跳过。

将您的 sql 重写为 return 只有 3 行(使用限制 3)- 这样就没有大的结果集需要处理

对您的代码的一些想法

这是您将对象接收到列表中的部分:

for (final Object[] objects : evntList) {
                final EvntDTO dto = new ExactTargetDailyMailDTO(
                        String.valueOf(objects[0]),
                        String.valueOf(objects[1]),....,....,);

  if(dto.getEvntName() matches some condition(){
  //change event name and other params accordingly
  }
  eventList.add(dto);

稍后您按顺序遍历该列表中的所有事件:

for (int i = 0; i < eventList.size(); i++) {

我不明白为什么不能执行您在 for 循环中执行的操作 而不是 将其添加到列表中。

检查 next 条目是否与 last 条目具有相同的电子邮件的部分 - 你应该能够撤销它查看 current 项是否与 previous 项具有相同的值。这样您就不必 "peek ahead" 在您的列表中。

您似乎也在根据这些电子邮件地址进行一些检查。如果您事先知道 remindersList 中的值,您应该能够将其用作查询的 条件 (AND email LIKE (?, ?, ?...) 减少行数 returned?

这里的问题不是结果集,而是你的代码。只需摆脱列表,并在结果检索循环内进行条件处理。并且去掉你添加到文件内容的部分,每次直接写入文件即可,而不是延迟。