Java @批量大小是明智的还是愚蠢的使用?

Java @批量大小是明智的还是愚蠢的使用?,java,hibernate,postgresql,jpa,Java,Hibernate,Postgresql,Jpa,首先,我将解释如何理解和使用@BatchSize: @BatchSize是为了批量加载对象的关系,从而减少对数据库的SQL请求。这特别适用于惰性@OneToMany关系 然而,它甚至对惰性的@OneToOne关系和@ManyToOne:如果您从数据库加载一个实体列表,并要求加载一个懒散的@*ToOne实体,它将批量加载实体,即使我只是使用加载列表中第一个实体的关系的测试 注意:如果有些人想要测试:这仅在实体尚未加载时显示:例如,如果您有一个带有manager的用户列表,并且列出了所有用户,当您将

首先,我将解释如何理解和使用
@BatchSize
@BatchSize
是为了批量加载对象的关系,从而减少对数据库的SQL请求。这特别适用于惰性
@OneToMany
关系

然而,它甚至对惰性的
@OneToOne
关系和
@ManyToOne
:如果您从数据库加载一个实体列表,并要求加载一个懒散的
@*ToOne
实体,它将批量加载实体,即使我只是使用加载列表中第一个实体的关系的测试

注意:如果有些人想要测试:这仅在实体尚未加载时显示:例如,如果您有一个带有manager的用户列表,并且列出了所有用户,当您将访问manager时,不会触发任何请求,因为它已加载

我在该方法中看到的唯一缺点是,如果您从数据库加载一个项目列表,但只使用其中的一部分。这是一个后筛选操作

那么让我们进入重点

让我们假设我做的一切都很好,从不做类似后期过滤的操作,即使它让我做本机SQL查询或使用DTO对象进行多选条件查询等等

在仔细考虑使用急速加载/连接并最终选择一个懒惰关系后,我是否可以考虑“<代码> @ BATCHSIZE 每一个懒惰的关系?”李>
  • 我是否有兴趣为
    @BatchSize
    搜索一个适当的值,或者我是否可以认为“越大越好”?这意味着“in”SQL运算符中的“是否有任何数字限制,可以使我的请求变得足够慢,不再有价值?我使用Postgres,但如果您有其他SGBD的答案,我也感兴趣
  • 可选问题:在类上使用
    @BatchSize
    似乎不会产生太多结果。我仍然必须注释每个惰性关系,我是否遗漏了它的一些内容,或者它是没有用的
  • 编辑:我的3点是,我得到了一个不同的行为

    假设我正在加载一个类“a”的实体列表,它与B有一个懒惰的一对一关系。现在我想打印B的所有creationDate。所以我正在做一个经典的2 for循环

    我现在用BatchSize注释了B:

    • @OneToMany没有用BatchSize注释:每组B在每次迭代中独立加载,没有批处理。因此,我对B类的注释似乎被完全忽略。即使我将一个值设置为“2”,并且一个集合中有6个条目,我对该集合也有一个查询。
      • @OneToMany被注释:我有加载批次的特定查询。如果我将批次大小固定为2,并且我总共有10个B accros,我只会收到5个请求:无论a的数量如何。如果我将其设置为100,我有1个B对象查询
    PS:我不考虑任何与B相关的查询,这些查询可能会触发以使用fetch-select/subselect加载B字段

    编辑2:我刚刚找到了这篇文章,虽然我在发布问题之前在谷歌上搜索过,但我猜我没有使用正确的词

    然而,我添加了一些不同的东西,这可能会导致不同的答案:当我想在每个关系上使用BatchSize时,都是在选择我是想要立即加载、使用join/select fetch还是想要延迟加载之后

  • 是的,
    @BatchSize
    用于惰性关联
  • Hibernate在大多数情况下都会执行多条语句,即使未初始化代理/集合的计数小于指定的批处理大小。有关更多详细信息,请参阅。此外,与较小的查询相比,较轻的查询可能会对系统的总体吞吐量产生积极的影响
  • 类级别上的
    @BatchSize
    表示实体的指定批量大小将应用于与该实体的所有
    @*ToOne
    惰性关联。请参阅
  • 您提供的链接问题/答案更关注优化和延迟加载的需求。当然,它们也适用于这里,但它们仅与批量加载无关,这只是可能的方法之一

    另一件重要的事情与链接答案中提到的急切加载有关,这表明如果总是使用某个属性,那么您可以通过使用急切加载获得更好的性能。对于集合,这通常是不正确的,在许多情况下,对于to-one关联,这也是不正确的

    例如,假设您有以下实体,当使用
    A
    时,对其使用
    bs
    cs

    public class A {
      @OneToMany
      private Collection<B> bs;
    
      @OneToMany
      private Collection<C> cs;
    }
    
    然后在
    bs
    cs
    之间创建完全笛卡尔积,并返回
    count(a.bs)x count(a.cs)
    结果集中每个
    a
    行,逐行读取并组合成
    a
    的实体及其
    bs
    cs
    的集合


    在这种情况下,批处理抓取是非常理想的,因为您首先读取
    A
    s,然后读取
    bs
    ,然后读取
    cs
    ,这样会产生更多的查询,但从数据库传输的数据总量要少得多。此外,单独的查询比带有联接的大型查询简单得多,并且更容易进行dat降低执行和优化的难度。

    1-我想我曾经读过一篇文章,说这不是一个很好的做法,这就是为什么我想知道,只要我意识到邮件过滤之类的问题,我就可以到处发送邮件。3-我有不同的行为,我编辑了我的问题以获取更多信息。请检查一下这个问题。Walfrat请查看我编辑的answer、 3)类级别上的
    @BatchSize
    仅适用于与这些实体的一个关联。1)
    select a from A
      left join fetch a.bs
      left join fetch a.cs