[Java Performance] 数据库性能最佳实践 - JPA和读写优化

本文探讨了数据库性能最佳实践,重点在Java Persistence API (JPA)的事务处理、写优化和读优化。介绍了如何通过事务管理、预编译语句和批量操作来提升JPA的性能,同时讨论了懒加载和立即加载策略对数据库查询效率的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据库性能最佳实践

当应用需要连接数据库时,那么应用的性能就可能收到数据库性能的影响。比如当数据库的I/O能力存在限制,或者因缺失了索引而导致执行的SQL语句需要对整张表进行遍历。对于这些问题,仅仅对应用代码进行优化可能是不够,还需要了解数据库的知识和特点。

示例数据库

该数据库表示了128只股票在1年内(261个工作日)的股价信息。

其中有两张表:STOCKPRICE和STOCKOPTIONPRICE。 STOCKPRICE中使用股票代码作为主键,另外还有日期字段。它有33408条记录(128 * 261)。 STOCKOPTIONPRICE中存放了每只股票在每天的5个Options,主键是股票代码,另外还有日期字段和表示Option号码的一个整型字段。它有167040条记录(128 * 261 * 5)。

JPA

对JPA的性能影响最大的是它使用的JDBC Driver。除此之外,还有一些其他因素也会影响JPA的性能。

JPA是通过对实体类型的字节码进行增强来提高JPA的性能的,这一点在Java EE环境中对用户是透明的。但是在Java SE环境中需要确保这些字节码操作的正确性。否则,会出现各种各样的问题影响JPA的性能,比如:

  • 需要懒加载(Lazy Load)的字段被立即加载(Eager Load)了
  • 保存到数据库中的字段出现了不必要的冗余
  • 应当保存到JPA缓存中的数据没有保存,导致本不必要的重取(Refetch)操作

JPA对于字节码的增强一般作为编译阶段的一部分。在实体类型被编译成为字节码后,它们会被后置处理程序(它们是实现相关的,也就是EclipseLink和Hibernate使用的后置处理程序是不同的)进行处理来增强这些字节码,得到经过优化了的字节码文件。

在有的JPA实现中,还提供了当类被加载到JVM中时,动态增强字节码的方法。需要为JVM指定一个agent,通过启动参数的形式提供。比如当希望使用EclipseLink的这一功能时,可以传入:-javaagent:path_to/eclipselink.jar

事务处理(Transaction Handling)

JPA可以使用在Java SE和Java EE应用中。区别在于事务的处理方式。

在Java EE中,JPA事务只是应用服务器的Java事务API(JTA)实现的一部分。它提供了两种方式用来处理事务的边界:

  • 容器管理事务(Container-Managed Transaction,CMT)
  • 用户管理事务(User-Managed Transaction, UMT)

顾名思义,CMT会将事务的边界处理委托给容器,而UMT则需要用户在应用中指定边界的处理方式。在合理使用的情况下,CMT和UMT并没有显著的区别。但是,在使用不当的情况下,性能就会出现差异了,尤其是在使用UMT时,事务的范围可能会定义的过大或者过小,这样会对性能造成较大的影响。可以这样理解:CMT提供了一种通用的和折中的事务边界处理方式,使用它通常会更安全,而UMT则提供了一种更加灵活的处理方式,但是灵活是建立在用户必须十分了解它的基础上的。

@Stateless
public class Calculator {
   
   
    @PersistenceContext(unitName="Calc")
    EntityManager em;
    @TransactionAttribute(REQUIRED)
    public void calculate() {
   
   
        Parameters p = em.find(...);
        // ...perform expensive calculation...
        em.persist(...answer...);
    }
}

上述代码使用了CMT(使用了@TransactionAttribute注解),事务的作用域是整个方法。当隔离等级是可重复读(Repeatable Read)时,意味着在进行计算(以上的Expensive Calculation注释行)时,需要的数据会一直被锁定,从而对性能造成了影响。

在使用UMT时,会更灵活一点:

@Stateless
public class Calculator {
   
   
    @PersistenceContext(unitName="Calc")
    EntityManager em;
    public void calculate() {
   
   
        UserTransaction ut = ... lookup UT in application server...;
        ut.begin();
        Parameters p = em.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值