休眠性能最佳实践?

2022-09-02 09:20:44

我正在使用Hibernate 3编写Web应用程序。

所以,过了一会儿,我注意到有些事情很慢。因此,我测试了休眠探查器,发现休眠会为简单操作进行不合理的许多db调用。原因当然是我加载了一个对象(这个对象有几个“父项”),而这些“父项”有其他“父项”。所以基本上休眠加载它们,即使我只需要基本对象。好吧,所以我研究了延迟加载。这导致我进入Lazyloading异常,因为我有一个MVC webapp。

所以现在我有点困惑,我最好的方法是什么。基本上,我需要的只是更新对象上的单个字段。我已经有了对象键。

我应该:1.深入研究延迟加载。然后重写我的应用程序以获得打开会话视图?2. 深入了解延迟加载。然后重写我的道更具体。例如,编写 DAO 方法,这些方法将返回仅包含每个用例所需内容的对象?可能有很多额外的方法...3.抓挠冬眠并自己做?4.现在真的想不出其他解决方案。有什么建议吗?

最佳实践是什么?


答案 1
  • 除非确实需要,否则不要使用联接。它们既不允许您使用延迟加载,也不允许您对关联使用2nd级缓存
  • 对大型集合使用 lazy=“extra”,在你询问它之前,它不会检索所有元素,你也可以使用 size() 方法,例如,无需从 DB 中获取元素
  • 如果可能,请使用 load() 方法,因为它在需要之前不会发出选择查询。例如,如果您有一本书和一位作者,并且想要将它们关联在一起,则不会发出任何选择,只会插入:

    Book b = (Book) session.load(Book.class, bookId);
    Author a = (Author) session.load(Author.class, authorId);
    b.setAuthor(a);
    session.save(b);
    
  • 使用命名查询(在 hbm 文件或@NamedQuery中),以便在每次查询期间不解析它们。在需要之前不要使用条件 API(在这种情况下,无法使用 ReadyStatement 缓存)

  • 在 Web 应用程序中使用 OSIV,因为它仅在需要时加载数据
  • 对只选项使用只读模式:。这将使Hibernate不在持久性上下文中保留所选实体的原始快照以进行进一步的脏检查。session.setReadOnly(object, true)
  • 用户 2 级缓存和查询缓存,用于主要读取和只读数据。
  • 使用 FlushMode.COMMIT 而不是 AUTO,以便 Hibernate 在更新之前不会发出选择,但要准备好这可能会导致写入过时的数据(尽管 Optimistic Locking 可以为您提供帮助)。
  • 查看批处理提取(批处理大小),以便一次选择多个实体/集合,而不是为每个实体/集合发出单独的查询。
  • 执行诸如“从实体中选择新实体(id,someField)”之类的查询,以便仅检索必填字段。看看结果转换器。
  • 如果需要,请使用批处理操作(如删除)
  • 如果使用本机查询,请显式指定哪些缓存区域应失效(默认情况下 - 全部)。
  • 查看树状结构的实例化路径和嵌套集。
  • 设置是为了在池中启用 PreparedStatment 缓存,并在默认情况下关闭数据库时启用数据库的语句缓存。c3p0.max_statements
  • 如果可能的话,使用无状态会话,它可以克服肮脏的检查,级联,拦截器等。
  • 不要将分页 (, ) 与包含集合联接的查询一起使用,这将导致从数据库提取所有记录,并且分页将由 Hibernate 在内存中发生。如果需要分页,理想情况下不应使用联接。如果您无法转义它,请再次 - 使用批量提取。setMaxResults()setFirstResult()

其实有很多窍门,但我现在想不起来了。


答案 2

您可以采取许多措施来加快休眠性能,例如:

  1. 启用 SQL 语句日志记录,以便您可以验证所有语句,甚至可以在测试期间检测 N+1 查询问题。
  2. 使用 FlexyPool 进行数据库连接管理和监控
  3. JDBC 批处理以减少提交 INSERT、UPDATE 和 DELETE 语句所需的往返次数。
  4. JDBC 语句缓存
  5. JPA 标识符优化器,如池化或池化 lo
  6. 选择紧凑型色谱柱类型
  7. 使用正确的关系:双向关系而不是单向关系,使用 for ,用于@OneToMany@MapsId@OneToOneSet@ManyToMany
  8. 以正确的方式使用继承,并出于性能原因首选SINGLE_TABLE
  9. 注意持久性上下文大小并避免长时间运行的事务
  10. 使用操作系统缓存,在跳转到第二级缓存之前进行数据库缓存,这对于在执行数据库复制时卸载主节点也很有用
  11. 通过 SQL 本机查询释放数据库查询功能
  12. 在多个一对一实体之间拆分写入,以 [减少乐观锁定误报,即使在修改某些实体时,也能有更好的机会命中数据库缓存。

推荐