为什么使用Hibernate进行查询缓存会使查询速度慢十倍?

Nils-Petter Nilsen:

我目前正在尝试将EJB3作为工作中的一个主要项目的前期准备。我正在研究的内容之一是查询缓存。

我已经制作了一个非常简单的域模型,其中包含JPA批注,@ Local业务接口和EJB-JAR中的@Stateless实现,并与一个非常简单的Web应用程序一起部署在EAR中,以进行一些基本测试。EAR无需任何修改即可部署在JBoss 5.0.1默认配置中。这很简单,并且按预期工作。

但是,我的最新测试涉及查询缓存,但得到了一些奇怪的结果:

  • 我有一个仅映射ID和字符串值的域类,并且已在该特定表中创建了大约10000行
  • 在业务Bean中,有一个非常简单的查询,SELECT m FROM MyClass m
  • 没有缓存,平均执行时间约为400毫秒
  • 启用查询缓存(通过查询提示)后,第一次执行当然会花费更长的时间,大约为1200ms。下一次执行平均需要3500毫秒!

这让我感到困惑,因此我启用了Hibernate的show_sql查看日志。未缓存,并且在第一次启用缓存的情况下执行,如预期那样记录了一个SELECT。当我应该获得缓存命中时,Hibernate为数据库表中的每一行记录一个SELECT。

那肯定可以解释执行时间慢的原因,但是谁能告诉我为什么会这样吗?

马特·索尼特(Matt Solnit):

查询缓存的工作方式是仅缓存查询返回的对象ID因此,您的初始SELECT语句可能会返回所有对象,并且Hibernate会将它们返回给您并记住ID。

但是,下一次发出查询时,Hibernate将遍历ID列表,并意识到它需要具体化实际数据。因此,它返回数据库以获取其余信息。并且每行执行一次SELECT,这正是您所看到的。

现在,在您想到“此功能显然已损坏”之前,它以这种方式工作的原因是查询缓存被设计为与第二级缓存协同工作。如果在第一次查询后将对象存储在L2高速缓存中,则Hibernate将转而查找那里以满足每个ID的请求。

我强烈建议您阅读《Hibernate的Java持久性》一书以了解有关此内容的更多信息。第13章特别介绍了优化查询以及如何有效使用缓存。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章