我在“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自动选择。
但我仍然不明白它是如何运作的。
如果有人可以提出一步一步的算法......:)
答案 0 :(得分:4)
我在网上找不到有关hibernate如何处理批量加载的任何信息,但根据您的信息判断,可以猜测以下内容:
为什么有11个批量加载器?
批量大小为20时,如果要最小化任何代理组合所需的加载器数量,基本上有两种选择:
batch_size/2
创建更多加载器(递归)示例:对于40号批次,您最终会得到40,20,10,9,8,7,6,5,4,3,2,1装载机的装载机。
为什么批量加载器可以初始化:20,10,9,8,7,6,5,4,3,2,1个代理?
我认为hibernate团队选择这个作为加载未初始化代理的“常见”数N和内存消耗所需的加载器数量之间的平衡。可能为0和batch_size
之间的每个N创建了一个加载器,但我怀疑加载器有相当大的内存占用所以这是一个权衡。算法可以是这样的(有根据的猜测):
n = batch_size; while (n > 10)
1.1。 loader(n); n = n / 2
for n = 0..10 create loader(n)
答案 1 :(得分:4)
这有助于避免创建大量不同的预准备语句。
需要解析每个查询(预准备语句),并且数据库需要执行其执行计划calculated and cached。此过程可能比已经缓存该语句的查询的实际执行要昂贵得多。
大量不同的语句可能会导致从缓存中清除其他缓存的语句,从而降低整体应用程序的性能。
此外,由于硬分析通常非常昂贵,因此执行多个缓存的预准备语句(包括多个数据库往返)通常比解析和执行新语句更快。因此,除了减少不同语句数量的明显好处之外,通过执行11个缓存语句检索所有119个实体实际上可能比创建和执行包含所有119个ID的单个新实体更快。
正如评论中已经提到的,Hibernate调用ArrayHelper.getBatchSizes
方法来确定给定最大批量大小的批量大小。