default_batch_fetch_size建议值

Tar*_*att 5 hibernate

我正在浏览一些hibernate教程并且遇到了default_batch_fetch_size.阅读专家评论" 可以在性能敏感的应用程序中使用Hibernate吗? "清楚地解释了重要性,但我试图理解为什么链接中使用的推荐值4,8,16或32.

关心塔伦

PCO*_*PCO 9

摘要:

当启用批量提取时,Hibernate会准备很多查询:这些查询需要占用大量内存,而这些内存无法使用.批量大小为1000将占用150 Mo的RAM.

因此,具有较低的一般批量(例如10,20或40)是最好的,仅使用@BatchSize注释为特定集合设置更大的批量大小.

详情:

这里解释了获取批量大小,了解Hibernate中的@BatchSize,"hibernate.default_batch_fetch_size"是一般参数,"@ BatchSize"注释允许覆盖特定关联的常规参数.

但这些解释并没有真正回答"为什么官方文件推荐值为4,8或16"的问题?显然,现代数据库可以在IN子句中处理超过16个值的查询,并且在IN子句中使用1000个值进行查询将允许执行更少的查询,从而允许更好的性能...所以为什么不设置批量为1000?

我做到了,我把1024作为批量大小,答案很快就出现了:tomcat服务器需要更多的时间来启动,在调试日志中我可以看到很多行"静态选择实体......".

发生的事情是Hibernate准备了数以千计的静态查询,这里是实体日志的一部分:

...
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?, ?, ?, ?, ?, ?, ?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?, ?, ?, ?, ?, ?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?, ?, ?, ?, ?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?, ?, ?, ?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?, ?, ?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?, ?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id in (?, ?)
Static select for entity Profile [PESSIMISTIC_READ]: select xxx_ with (holdlock, rowlock ) where id = ?
...
Run Code Online (Sandbox Code Playgroud)

如您所见,Hibernate准备批量提取请求,但不是所有请求.Hibernate准备所有1,2,3 .... 10个参数的请求,然后只准备一些args等于batchSize /(2 ^ n)的请求.例如,如果batchSize = 120 => 120,60,30,15,10,9,8,......,2,1

所以我尝试用不同数量的元素批量获取集合,结果如下:

  • 为了获取18个项目,hibernate进行了2个查询:一个包含16个项目,另一个包含2个项目.

  • 对于获取16个项目,hibernate使用16个项目进行了1次查询.

  • 为了获取12个项目,hibernate进行了2个查询:一个有10个项目,一个有2个项目.

Hibernate只使用了启动时准备的语句.

之后,我监视了所有这些准备好的语句的RAM使用情况:

  • with batchSize = 0 => 94 Mo(这是我的参考)

  • batchSize = 32 => 156 Mo(带参考值+62 Mo)

  • batchSize = 64 => 164 Mo(参考值为+ 68 Mo)

  • batchSize = 1000 => 250 Mo(+156!Mo参考)

(我的项目中等规模,约300个实体)

现在是结论的时候了:

1)批量大小会对启动时间和内存消耗产生很大影响.它不会与批量大小成线性关系,批量大小为80,比批量大小为10倍.

2)Hibernate无法检索具有任何大小批量的项目集合,它只使用准备好的批量查询.如果设置batchSize = 120,则准备好的查询将是具有120,60,30,15,10,9,8,7,6,5,4,3,2和1个参数的查询.因此,如果您尝试获取包含220个项目的集合,则会触发4个查询:第一个将检索120个项目,第二个将检索第二个60,第三个30和第四个10.

这解释了推荐的batchSizes低的原因.我建议设置一个像20这样的低全局batchSize(20对我而言似乎比16更好,因为它不会生成比16更准备的查询)并且仅在需要时设置特定的更大的@BatchSize.

(我使用的是Hibernate 5.1)


Nik*_*rov 7

我们正在hibernate.default_batch_fetch_size = 100生产中使用.因此,在某些情况下,我们有3个查询而不是300个,所以这对我们的数据库来说是一个很好的性能提升.

  • 对于那些通过 Spring Data 使用 Hibernate 的人。如果要将其指定为全局参数,请使用下一个属性 `spring.jpa.properties.hibernate.default_batch_fetch_size=50 spring.jpa.properties.hibernate.batch_fetch_style=dynamic` (2认同)

小智 5

关于内存/启动时间的问题。尝试使用:

 <property name="hibernate.batch_fetch_style" value="dynamic" />
Run Code Online (Sandbox Code Playgroud)

只有一条带有“where id = ?”的准备语句,但会话中同一类型实体的批量获取是动态构造的,限制为hibernate.default_batch_fetch_size。