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

Mac*_*eft 7 java algorithm optimization fetching-strategy java-ee

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

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

但我仍然不明白它是如何工作的.

  1. 为什么11批装载机?
  2. 为什么批量加载器可以初始化:20,10,9,8,7,6,5,4,3,2,1代理?

如果有人可以提出一步一步的算法...... :)

Mig*_*ing 5

我在网上找不到任何有关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. ...

为什么批量加载器可以初始化:20、10、9、8、7、6、5、4、3、2、1 个代理? 我认为 hibernate 团队选择此作为加载“公共”数量 N 的未初始化代理所需的加载器数量与内存消耗之间的平衡。可以为 0 到 0 之间的每个 N 创建一个加载程序batch_size,但我怀疑加载程序有相当大的内存占用,因此这是一个权衡。该算法可以是这样的(有根据的猜测):

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

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

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

  • 要了解其背后的算法,您可以查看 Arrayhelper.GetBatchSizes 的源代码 (3认同)

Dra*_*vic 5

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

每个查询(准备好的语句)都需要解析,并且其执行计划需要由数据库计算和缓存。该过程可能比实际已执行了该语句的查询的执行成本高得多。

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

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

正如注释中已经提到的那样,Hibernate调用ArrayHelper.getBatchSizes方法来确定给定最大批处理大小的批处理大小。