简体   繁体   English

休眠:实体图的n + 1和性能降低

[英]Hibernate: n+1 and slow performance with Entity Graph

We did an upgrade to Hibernate 5, after which we began to experience performance issues. 我们对Hibernate 5进行了升级,此后我们开始遇到性能问题。

We have several entities with associations like this: 我们有几个具有以下关联的实体:

@Entity
@Table(name = "EVENT")
public class Event {
    @Id
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "LOCATION", referencedColumnName = "ID")
    private Location location;
}

@Entity
@Table(name = "LOCATION")
public class Location {
    @Id
    @Column(name = "ID")
    private Long id;
}

We are using the Criteria API to fetch the data from the database. 我们正在使用Criteria API从数据库中获取数据。

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Event> query = cb.createQuery(Event.class);
Root<Event> from = query.from(Event.class);
query.select(from).where(from.get("id").in(1, 2, 3));
TypedQuery<Event> tQuery = entityManager.createQuery(query);
tQuery.setMaxResults(1000);
tQuery.getResultList();

Previously (version 4, old Criteria API), Hibernate generated one select with a join statement that fetched all the data, just based on the FetchType.EAGER, but with Hibernate 5, it creates multiple additional queries for fetching the 'location' data - the N+1 problem. 以前(第4版,旧的Criteria API),Hibernate生成了一个join语句,仅基于FetchType.EAGER提取了所有数据,但是使用Hibernate 5,它创建了多个附加查询来获取“位置”数据- N + 1问题。

Now, we have tried JPA Entity Graph, with mixed results. 现在,我们尝试了JPA实体图,但结果复杂。 We were able to reduce the number of queries (no N+1 now), but on the other hand, the performance of the system is even slower. 我们能够减少查询的数量(现在没有N + 1了),但是另一方面,系统的性能甚至更慢。

My questions are: 我的问题是:

  1. what other ways are there to remove N+1 queries problem? 还有什么其他方法可以消除N + 1查询问题?
  2. under what circumstances could Entity Graphs have negative performance impact? 实体图在什么情况下会对性能产生负面影响?

(We use SQL Server, Tomcat, Hibernate 5.2.10, Java 8.) (我们使用SQL Server,Tomcat,Hibernate 5.2.10,Java8。)

To get the earlier behaviour of fetching location data along with join in a single query can be achieved by adding the fetch 为了获得较早的fetching location data along with join in a single query中进行fetching location data along with join in a single query行为,可以通过添加fetch来实现

from.fetch("location", javax.persistence.criteria.JoinType.LEFT);

So your code would look like: 因此您的代码如下所示:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Event> query = cb.createQuery(Event.class);
Root<Event> from = query.from(Event.class);
from.fetch("location", javax.persistence.criteria.JoinType.LEFT);
query.select(from).where(from.get("id").in(1, 2, 3));
TypedQuery<Event> tQuery = entityManager.createQuery(query);
tQuery.setMaxResults(1000);
tQuery.getResultList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM