java - 处理来自 PostgreSQL 的大量数据

标签 java postgresql hibernate jpa jdbc

我正在寻找一种方法如何在合理的时间内处理从数据库加载的大量数据。

我面临的问题是我必须从数据库中读取所有数据(目前大约有 30M 行),然后用 Java 处理它们。处理本身不是问题,但从数据库中获取数据才是问题。提取通常需要 1-2 分钟。但是,我需要它比这快得多。我使用以下查询将数据从数据库直接加载到 DTO:

select id, id_post, id_comment, col_a, col_b from post_comment

其中 id 是主键,id_postid_comment 是各自表的外键,col_acol_b 是小型 int 数据类型的列。带有外键的列有索引。 我目前在工作中使用的工具是 Java、Spring Boot、Hibernate 和 PostgreSQL。

到目前为止,我想到的唯一选择是

  1. 为这个查询放弃 hibernate ,并尝试使用普通的 jdbc 连接,希望它会更快。
  2. 将处理算法从 Java 完全重写为 SQL 过程。

我是否遗漏了什么或者这些是我唯一的选择?我愿意接受任何想法。 请注意,我只需要读取数据,而不是以任何方式更改它们。

编辑:所用查询的解释分析

"Seq Scan on post_comment (cost=0.00..397818.16 rows=21809216 width=28) (actual time=0.044..6287.066 rows=21812469 loops=1), Planning Time: 0.124 ms, Execution Time: 8237.090 ms"

最佳答案

您需要一次处理所有行,还是可以一次处理一行?

如果您可以一次处理一个,您应该尝试使用可滚动的结果集。

org.hibernate.Query query = ...;
query.setReadOnly(true);
ScrollableResults sr = query.scroll(ScrollMode.FORWARD_ONLY);

while(sr.next())
{
    MyClass myObject = (MyClass)sr.get()[0];
    ... process row for myObject ... 
}

这将仍然记住实体管理器中的每个对象,因此会变得越来越慢。为避免该问题,您可以在完成后从实体管理器中分离对象。这只能在对象未被修改的情况下完成。如果修改了它们,则不会保留更改。

org.hibernate.Query query = ...;
query.setReadOnly(true);
ScrollableResults sr = query.scroll(ScrollMode.FORWARD_ONLY);

while(sr.next())
{
    MyClass myObject = (MyClass)sr.get()[0];
    ... process row for myObject ... 
    entityManager.detach(myObject);
}

关于java - 处理来自 PostgreSQL 的大量数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54874407/

相关文章:

sql - 最多允许 10 个具有相同 GUID 的项目

java - 如何在 JPA 中重新打开连接

java - Hibernate OneToOne 映射反向?

hibernate - 如何在Grails中的hasMany关系中指定查询?

sql - 如何选择具有相同时间顺序的所有值?

sql - 将 SELECT 结果与另一个表中的值相乘

java - 组合两个 CharSequence 变量

java - 列表的自动 XmlRootElement 包装器

java - ELKI 专家光学

java - 如何从数组中删除图像