高性能Java持久化的技巧

1:SQL语句日志如果您用了生成符合自己使用习惯的语句的框架,则应始终验证每个语句的有效性和效率。测试时使用断言机制验证更好,因为即使在提交代码之前,也可以捕获N + 1个查询问题。

2:连接管理数据库的连接开销非常大,因此您应该始终使用连接池机制。由于连接数由底层数据库集群的功能给出,所以您需要尽可能快地释放连接。在性能调优中,你总是要测量、设置出正确的连接池,池的大小又是差不多的。 但像FlexyPool这样工具可以帮助您找到合适的大小,即使您已经将应用程序部署到生产环境中。

3:JDBC批处理JDBC批处理允许我们在单个数据库往返中发送多个SQL语句。性能增益在驱动程序和数据库端都很重要。PreparedStatements 非常适合批处理,而某些数据库系统(例如 Oracle)仅支持用于预处理语句的批处理。由于JDBC为批处理定义了独特的API(例如PreparedStatement.addBatch和PreparedStatement.executeBatch),如果您手动生成语句,那么您应该从一开始就知道是否应该使用批处理。 使用Hibernate,您可以切换到使用单个配置的批处理。Hibernate 5.2 提供了会话级别的批处理,所以在这方面更加灵活。

4:语句缓存语句缓存是您可以轻松利用的最鲜为人知的性能优化之一。 根据基础的JDBC驱动程序,可以在客户端(驱动程序)或数据库端(语法树甚至执行计划)上缓存PreparedStatements。

5:Hibernate 标识符当使用Hibernate时,IDENTITY生成器不是一个好的选择,因为它禁用了JDBC批处理。TABLE生成器更糟糕,因为它使用一个单独的事务来获取新的标识符,这会对底层事务日志以及连接池造成压力,因为每次我们需要一个新的标识符时都需要单独的连接。SEQUENCE是正确的选择,甚至从2012版本就开始支持SQL Server。对于SEQUENCE标识符,Hibernate一直提供优化器,如 pooled 或 pooled-lo,这可以减少获取新的实体标识符值所需的数据库往返次数。

6:选择正确的列类型您应该始终在数据库端使用正确的列类型。 列类型越紧凑,数据库工作集中可容纳的条目越多,索引将更好地适应于内存。 为此,您应该利用特定于数据库的类型(例如PostgreSQL中的IPv4地址的inet),尤其是在实现新自定义类型时,Hibernate非常灵活。


7:关系Hibernate 带有许多关系映射类型,但并不是所有的关系映射类型在效率上都是相等的。应该避免单向集合和 @ManyToMany 列表。如果您确实需要使用实体集合,则首选双向 @OneToMany关联。对于 @ManyToMany 关系,使用 Set(s),因为在这种情况下它们更高效,或者简单地映射链接的多对多表,并将 @ManyToMany 关系转换为两个双向的 @OneToMany 关联。然而,与查询不同,集合不够灵活,因为它们不易分页,这意味着当子关联的数量相当高时,我们不能使用它们。出于这个原因,你应该考虑一个集合是否真的有必要。 在许多情况下,实体查询可能是更好的选择。

8:继承就继承而言,面向对象语言和关系数据库之间的不匹配变得更加明显。 JPA提供了SINGLE_TABLE,JOINED和TABLE_PER_CLASS来处理继承映射,每个策略都有其优缺点。SINGLE_TABLE在SQL语句方面表现最好,但由于我们不能使用NOT NULL约束,所以我们在数据完整性方面失败了。当同时提供更复杂的语句时,JOINED采用数据完整性限制。 只要你不使用基本类型的多态查询或@OneToMany关联,这个策略就没有问题。 它的真正的作用在于对数据访问层上由策略模式支持的多态@ManyToOne关联。应该避免使用TABLE_PER_CLASS,因为它不会生成有效的SQL语句。

9:持久性上下文的大小在使用 JPA 和 Hibernate 时,应该始终关注持久性上下文的大小。 出于这个原因,您不应该过多地使用托管实体。 通过限制托管实体的数量,我们可以获得更好的内存管理,并且默认的检查机制也将更加高效。

10:只抓取必要的东西获取太多的数据可能是导致数据访问层性能出问题的首要原因。 一个问题是,即使是只读的 Projections,实体查询也是专用的。DTO projections更适合于获取自定义视图,而实体只能在业务流需要修改时才能获取。EAGER抓取是最糟糕的,您应该避免反模式(Anti-Pattern),例如 Open-Session in View。


11:高速缓存关系数据库系统使用许多内存缓冲区结构来避免磁盘访问。 数据库缓存经常被忽视。 我们可以通过适当调整数据库引擎来显着降低响应时间,以便工作集驻留在内存中,而不是一直从磁盘中获取。应用程序级缓存对于许多企业应用程序来说是不可选的。 应用程序级缓存可以减少响应时间,同时为数据库关闭以进行维护或由于某些严重系统故障提供只读辅助存储库。二级缓存对于减少读写事务响应时间非常有用,特别是在主从复制体系结构中。 根据应用程序的要求,Hibernate允许你在READ_ONLY,NONSTRICT_READ_WRITE,READ_WRITE和TRANSACTIONAL之间进行选择。

12:并发控制在性能和数据完整性方面,事务隔离级别的选择是非常重要的。 对于多请求Web流程,为避免丢失更新,您应该对分离的实体或 EXTENDED 持久性上下文使用 optimistic 锁定。为避免optimistic locking误报,您可以使用无版本 optimistic 并发控制或基于读写的属性集来拆分实体。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值