Hibernate批量获取算法如何工作?

时间:2010-08-12 15:07:12

标签: java algorithm optimization java-ee fetching-strategy

我在“Manning-Java Persistence with Hibernate”中找到了批量获取算法的描述:

  

什么是真正的批量提取   算法? (...)想象一下批量大小   20和总数119   必须是未初始化的代理   分批装。在启动时,   Hibernate读取映射元数据   并创建11个批量加载器   内部。每个装载器知道多少   它可以初始化的代理:20,10,9,   8,7,6,5,4,3,2,1。目标是   最小化内存消耗   加载器创建和创建足够   每个可能批次的装载机   可以生成提取。另一个目标是   最小化SQL的数量   选择,显然。要初始化119   代理Hibernate执行七个   批次(你可能预计有六个,   因为6×20> 119)。批次   应用的装载机是五个   时间20,一次10,一次9,   由Hibernate自动选择。

但我仍然不明白它是如何运作的。

  1. 为什么有11批装载机?
  2. 为什么批量加载器可以初始化:20,10,9,8,7,6,5,4,3,2,1个代理?
  3. 如果有人可以提出一步一步的算法......:)

2 个答案:

答案 0 :(得分:4)

我在网上找不到有关hibernate如何处理批量加载的任何信息,但根据您的信息判断,可以猜测以下内容:

为什么有11个批量加载器?

批量大小为20时,如果要最小化任何代理组合所需的加载器数量,基本上有两种选择:

  • 为1,2,3,4,5,6,7,... 20,21,22,23,... N个未初始化代理创建一个加载器(愚蠢!)或
  • 为1到9之间的任何N创建一个加载器,然后为batch_size/2创建更多加载器(递归)

示例:对于40号批次,您最终会得到40,20,10,9,8,7,6,5,4,3,2,1装载机的装载机。

  1. 如果您有33个未初始化的代理,则可以使用以下加载器:20,10,3
  2. 如果您有119个未初始化的代理,则可以使用以下加载器,40(x2),20,10,9
  3. ...
  4. 为什么批量加载器可以初始化:20,10,9,8,7,6,5,4,3,2,1个代理? 我认为hibernate团队选择这个作为加载未初始化代理的“常见”数N和内存消耗所需的加载器数量之间的平衡。可能为0和batch_size之间的每个N创建了一个加载器,但我怀疑加载器有相当大的内存占用所以这是一个权衡。算法可以是这样的(有根据的猜测):

    1. n = batch_size; while (n > 10)

      1.1。 loader(n); n = n / 2

    2. for n = 0..10 create loader(n)

答案 1 :(得分:4)

这有助于避免创建大量不同的预准备语句。

需要解析每个查询(预准备语句),并且数据库需要执行其执行计划calculated and cached。此过程可能比已经缓存该语句的查询的实际执行要昂贵得多。

大量不同的语句可能会导致从缓存中清除其他缓存的语句,从而降低整体应用程序的性能。

此外,由于硬分析通常非常昂贵,因此执行多个缓存的预准备语句(包括多个数据库往返)通常比解析和执行新语句更快。因此,除了减少不同语句数量的明显好处之外,通过执行11个缓存语句检索所有119个实体实际上可能比创建和执行包含所有119个ID的单个新实体更快。

正如评论中已经提到的,Hibernate调用ArrayHelper.getBatchSizes方法来确定给定最大批量大小的批量大小。