防止 OpenJPA N+1 在地图上选择性能问题

发布于 2024-10-14 17:39:29 字数 1111 浏览 2 评论 0原文

当我有一个包含映射的实体时,例如

@Entity
public class TestEntity {
    @ElementCollection(fetch = FetchType.EAGER)
    Map<String, String> strings = new HashMap<String, String>();
}

,当我选择多个实体(SELECT z FROM TestEntity z)时,OpenJPA 2.0 会对每个 TestEntity 执行一个查询来获取映射,即使我使用了 FetchType.EAGER。当 Map 值是实体并且我使用 @OneToMany 而不是 @ElementCollection 时,也会发生这种情况。原则上,通过一个查询可以更有效地完成此操作,该查询为所有返回的 TestEntities 选择所有映射条目。对于集合值字段,OpenJPA 默认情况下已经执行此操作(openjpa.jdbc.EagerFetchMode" value="parallel"),但它似乎在这个简单的实体上失败。(与 value="join" 相同的问题)。

我可以做点什么吗有没有一种简单的方法来告诉 OpenJPA 不要对每个实体执行查询而只执行一个查询? 或者是否已经计划进行任何改进此问题的工作(我将其提交到 https://issues 下。 apache.org/jira/browse/OPENJPA-1920)?

这对我们来说是一个问题,因为我们希望获取(并分离)大约 1900 个产品的列表,而使用 OpenJPA 需要花费近 15 秒的时间。我自己的本机查询只需要不到一秒钟的时间。

只需要编写一个本机查询不会有太大问题,但我们使用的映射位于可重用的 StringI18N 实体内,该实体从多个不同的实体引用(并且可以深入对象图),因此本机查询是一种维护头痛。 非常感谢任何提高性能的帮助。

编辑:显式使用 JOIN FETCH 也没有帮助: “从 TestEntity z JOIN FETCH z.strings 中选择 z” OpenJPA 的 TRACE 仍然显示它为每个单独的 TestEntity 执行一个 SQL 语句。

When I have an entity that contains a Map, e.g.

@Entity
public class TestEntity {
    @ElementCollection(fetch = FetchType.EAGER)
    Map<String, String> strings = new HashMap<String, String>();
}

and I select multiple entities (SELECT z FROM TestEntity z), OpenJPA 2.0 performs one query for each TestEntity to fetch the map, even though I used FetchType.EAGER. This also happens when the Map value is an entity and I use @OneToMany instead of @ElementCollection. In principle this can be done more efficiently with one query that selects all the map entries for all returned TestEntities. For Collection-valued fields OpenJPA already does this by default (openjpa.jdbc.EagerFetchMode" value="parallel") but it seems to fail on this simple entity. (Same problem with value="join").

Could I be doing something wrong? Is there an easy way to tell OpenJPA to not perform a query per entity but only one?
Or is there already any work planned on improving this (I filed it under https://issues.apache.org/jira/browse/OPENJPA-1920)?

It is a problem for us because we wish to fetch (and detach) a list of about 1900 products which takes almost 15 seconds with OpenJPA. It takes less than a second with my own native query.

Having to write only one native query wouldn't be much of a problem but the map we use is inside a reusable StringI18N entity which is referenced from several different entities (and can be deep in the object graph), so native queries are a maintenance headache.
Any help getting performance up is greatly appreciated.

EDIT: explicitly using JOIN FETCH does not help either:
"SELECT z FROM TestEntity z JOIN FETCH z.strings"
OpenJPA's TRACE still shows that it executes one SQL statement for each individual TestEntity.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

°如果伤别离去 2024-10-21 17:39:29

这可能会很痛苦(更正:我知道这会很痛苦),但是您是否尝试过将 2 字段 TestEntity 实际映射为完整的 JPA 持久 @Entity

我知道 Hibernate 过去对待 @ElementCollection 的方式与对待 @OneToMany 的方式相当不同 - OpenJPA 很可能会做类似的事情。

It might be a pain (correction: I know it'll be a pain) but have you tried actually mapping your 2-field TestEntity as a full JPA-persisted @Entity?

I know that Hibernate used to treat @ElementCollections rather differently to @OneToManys for example - OpenJPA could well be doing something similar.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文