每次使用相同的参数值调用findOne(String id)时,Hibernate JPA都会生成select查询

时间:2018-05-18 12:16:39

标签: hibernate jpa spring-data-jpa query-cache hibernate-jpa

在我们的例子中,Hibernate findOne(String id)占用了很多时间(超过300毫秒)。这也不一致。对于某些请求,它会在不到100毫秒的时间内返回结果。

所以我们想要提高findOne的性能,它不应该超过100毫秒的时间。由于该表具有超过100k的记录,因此我们为选择查询中涉及的实体建立了索引。

我们正在为每个客户端请求调用此findOne方法。只有where子句中的值才会更改,而不会更改此中涉及的列或实体。

所以基本上,如果Hibernate可以创建/生成一次select查询并将其重用于存储库中的所有findOne调用,那就太棒了。

有人可以帮我这个吗?

1 个答案:

答案 0 :(得分:0)

您可以在此处考虑一些优化。

  1. HTTP会话
  2. 二级缓存
  3. 尽可能使用@NamedQuery
  4. 不要使用基于字符串的主键。
  5. HTTP会话缓存

    当客户端进行身份验证且值不存在时,您始终可以使用#findOne方法在HTTP会话中存储您获取的对象。这将消除对所有后续经过身份验证的请求的查询。您必须考虑的唯一问题是,如果当前用户修改了相关对象,您将需要使用更新后的副本替换会话中的值。

    许多Web应用程序都使用此机制。如果您曾登录过信用卡或银行的在线帐户系统并致电他们进行更改,那么您可能已经注意到必须退出并重新登录才能看到这些更改。这是相同的概念。

    二级缓存

    即使对于使用Hibernate的非基于HTTP的应用程序,此解决方案也非常有用。在这种情况下,您有一个位于应用程序端的数据存储区,您可以将其配置为存储不常更改的信息的查询结果。如果条目尚未过期,Hibernate将首先从缓存中保留水分,而不是将每个查询的数据库和网络成本转移到缓存中存在的内容。

    2LC的优点在于,如果要进行缓存,您可以配置每个查询,还可以为每个实体类型配置不同的超时和其他配置选项。

    @NamedQuery

    有时,您执行的复杂查询会以重新分析的JPQL / HQL为代价。如果您发现这是一个问题,您可能需要查看是否可以将查询移动到静态@NamedQuery

    @NamedQuery的好处是底层解析树的解析,验证和构建在应用程序boostrap上完成一次。这意味着在运行时,Hibernate只需获取该定义,获取预先生成的SQL,应用参数绑定并将其交给数据库。缺少参数类型验证,开销非常小。

    没有基于字符串的键

    根据您的数据库平台,基于字符串的主键可能比其数字计数器部分执行得更糟,特别是如果您的查询涉及连接。如果您的字符串字段配置为支持unicode(例如NVARCHAR或NCHAR列),则会使问题复杂化。

    @NaturalId使用字符串是完全正常的,因为您通常只是在该字段中应用where谓词,您可以根据查询的要求应用各种索引。

    但我建议您的查询是否使用基于字符串的主键,将其移至@NaturalId并使用基于代理数字的键作为主键。您会注意到,表连接会显着提高性能,因为它们之间的比较和哈希查找要快得多。