【问题标题】:JPA/Hibernate query optimization with null values具有空值的 JPA/Hibernate 查询优化
【发布时间】:2010-09-29 08:05:33
【问题描述】:

我正在使用 Hibernate 的 JPA 实现,并且看到性能很差,因为为每个获取的实体发出了多个 SQL 查询。如果我使用连接的 JPA 查询,它只会生成一个 SQL 查询,但没有找到将空关系的行。

例如,考虑这个简单的架构。一个人住在一个​​地址并受雇于一家公司。地址和雇主都是可选的,因此可以为空。

@Entity
public  class Person {
    public name;

    @ManyToOne
    @Column(nullable=true)
    public Address address

    @ManyToOne
    @Column(nullable=true)
    public Company employer
}

@Entity
public  class Address {
    address attributes ...
}

@Entity
public  class Company {
    company attributes ...
}

上面没有显示的是每个JPA实体都有某种ID(key):

@Id
public Integer id;

我看到的问题是对 Person 的单个 JPA 查询会导致对数据库的多个 SQL 查询。例如,以下 JPA 查询:

select p from Person p where ...

SQL 查询的结果:

select ... from Person where ...

还有以下对每个检索到的人的 SQL 查询:

select ... from Address a where a.id=xxx
select ... from Company c where c.id=yyy

这会对性能产生巨大影响。如果查询结果集为 1000 人,则生成 1+1000+1000=2001 条 SQL 查询。

所以我尝试通过强制加入来优化 JPA 查询:

select p from Person p join p.address a join p.employer e where ...

或:

select p, a, e from Person p join p.address a join p.employer e where ...

这会导致一个带有一堆连接的 SQL 查询。问题是如果地址或雇主为空,则连接查询将找不到它。

所以我要么使用慢的无连接查询,要么使用不检索行的快速连接查询将使关系为空。我一定在这里遗漏了一些东西。肯定有一种方法可以实现快速完整的查询。

【问题讨论】:

    标签: performance hibernate jpa jakarta-ee hql


    【解决方案1】:

    我的猜测是你需要一个左连接,即,

    SELECT p FROM Person p LEFT JOIN p.address a LEFT JOIN p.employer e WHERE...
    

    this blog entry for an example

    请注意,我实际上并没有在 JPA 中尝试过,但它在 HQL 中运行良好,这在许多方面都是 JPA 标准的基础。

    它不能使用普通连接的原因是默认是内连接。

    【讨论】:

      【解决方案2】:

      尝试在 Address 和 Company 实体上设置批处理大小 (@BatchSize)。它不会将它们加载到连接中(这就是您所追求的吗?),但每次加载时它都会加载一堆。批量大小表示当它发现需要一个时应该加载多少。

      如果您的批量大小为 1(默认值),并加载 10 个人。然后遍历他们,读取他们的地址和公司项目,然后 hibernate 将为这 10 个人进行一次查询,然后每次需要其中一个人的地址或公司时,它都会查询该人的地址。

      如果您在 Address 实体上设置了 7 的批量大小,那么当您读取第一个地址时,它会看到当前代理的地址超过 7 个,并且会去获取其中的 7 个地址。

      如果您的 Address 和 Company 的 BatchSize 为 7,并且您正在迭代 10 个人,那么这将导致 5 个查询,而不是目前的 21 yo。仍然不是一个连接将给你的 1。但是,在您只想要 Person 对象并且不会触及嵌入其中的 Address/Company 实体的情况下,连接会更慢(例如,您只想获取人员 ID 的列表,或者计算有多少是男性/女性)

      看看: http://hibernate.org/hib_docs/v3/reference/en/html/performance.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-05
        • 2012-05-18
        • 1970-01-01
        • 2018-09-23
        • 2012-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多