我在"Manning - Java持久化带Hibernate“中找到了对批取算法的描述:
什么是真正的批取算法?(.)假设批处理大小为20,而必须以批方式加载的未初始化代理总数为119个。在启动时,Hibernate读取映射元数据,并在内部创建11个批加载器。每个加载程序都知道它可以初始化多少代理: 20、10、9、8、7、6、5、4、3、2、1。目的是将创建加载程序的内存消耗降到最低,并创建足够多的加载器,以便可以生成每一个可能的批取。另一个目标显然是最小化SQL选择的数量。要初始化119个代理,Hibernate执行七个批(您可能期望6个,因为6x20> 119)。应用的批处理加载器为5乘20、1乘10和1倍9,由Hibernate自动选择。
但我还是不明白它是怎么工作的。
如果有人可以逐步提出算法. :)
发布于 2011-06-09 13:39:17
我无法在web上找到关于hibernate如何处理批加载的任何信息,但从您的信息来看,可以猜到如下:
为什么是11批装载机?
在批处理大小为20的情况下,如果您希望最小化(任何组合的代理)所需的加载程序的数量,基本上有两个选项:
batch_size/2(recursively)创建更多的加载程序
例如:对于批处理大小40,您将得到40,20,10,9,8,7,6,5,4,3,2,1装载器。
如果有33个未初始化的代理,可以使用以下加载程序: 20、10、3
(如果有119个未初始化的代理),可以使用以下加载程序: 40(x2)、20、10、9
为什么批加载程序可以初始化: 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)发布于 2015-07-03 08:55:16
这有助于避免创建大量不同的准备语句。
每个查询(准备好的语句)都需要由数据库解析,其执行计划需要是calculated and cached。这个过程可能比实际执行已经缓存语句的查询要昂贵得多。
大量不同的语句可能导致清除缓存中的其他缓存语句,从而降低应用程序的整体性能。
此外,由于硬解析通常非常昂贵,执行多个缓存的准备语句(包括多个数据库往返)通常比解析和执行新语句更快。因此,除了减少不同语句数量的明显好处外,通过执行11个缓存语句来检索所有119个实体可能比创建和执行包含所有119个ids的单个新语句更快。
正如注释中已经提到的,Hibernate调用ArrayHelper.getBatchSizes方法来确定给定最大批大小的批处理大小。
https://stackoverflow.com/questions/3469147
复制相似问题