一个方法内部只有查询并且是大量查询优化

一个方法内部只有查询并且是大量查询优化

问题分析

以前的方法是没有使用任何事务的, 所以使用的不是同一个会话连接

// 获取会话入口, SqlSessionTemplate.java
SqlSession sqlSession = getSqlSession(
    SqlSessionTemplate.this.sqlSessionFactory,
    SqlSessionTemplate.this.executorType,
    SqlSessionTemplate.this.exceptionTranslator);
// SqlSessionUtils.java
SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
SqlSession session = sessionHolder(executorType, holder);
if (session != null) {
    return session;
}

x6Cip4.png

从最初的阿里云提供的 应用实时监控服务 ARMS, 可以看出一个方法内部出现大量查询的时候, 不断的获取(可能是创建)连接、 执行、 回收(可能是释放)连接, 几十次加起来耗时也不少

优化使用同一个连接(会话)

使用同一个连接的情况下, 需要使用到事务(注解事务)

@Transactional(readOnly = true)
public OrderDetailResp orderDetail(@Valid OrderDetailRqt orderDetailRqt) {
    Long memberMasterId = orderDetailRqt.getMasterId();
    Long orderId = orderDetailRqt.getOrderId();

或者使用到手动事务 (建议使用注解方式)

@Autowired
private PlatformTransactionManager platformTransactionManager;

@Autowired
private TransactionTemplate TransactionTemplate;

@Override
public OrderDetailResp orderDetail(@Valid OrderDetailRqt orderDetailRqt) {
    Long memberMasterId = orderDetailRqt.getMasterId();
    Long orderId = orderDetailRqt.getOrderId();

     TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager);
     transactionTemplate.setReadOnly(Boolean.FALSE);
     transactionTemplate.setIsolationLevel(TransactionTemplate.getIsolationLevel());
     transactionTemplate.setPropagationBehavior(TransactionTemplate.getPropagationBehavior());
     transactionTemplate.setTimeout(TransactionTemplate.getTimeout());
     TransactionStatus transaction = platformTransactionManager.getTransaction(transactionTemplate);

    OrderDetailResp orderDetailResp = new OrderDetailResp();
    try {
        orderDetailResp.setOrderBaseComposite(orderCompositeManager.getOrderBaseComposite(orderId));
        orderDetailResp.setOrderLogisticsComposite(orderCompositeManager.getOrderLogisticsComposite(orderId));
        orderDetailResp.setOrderGoodsComposites(orderCompositeManager.getOrderGoodsCompositeList(orderId));
        orderDetailResp.setOrderOtherComposite(orderCompositeManager.getOrderOtherComposite(orderId));

        OrderServeInfo orderServeInfo = super.getOrderServeInfoForTeamMember(orderId, memberMasterId, 1);
    	//  其他查询省略
    } finally {
        platformTransactionManager.commit(transaction);
    }
    return orderDetailResp;
}

x6AMy4.png

到此, 方法内部大量查询都是使用同一个连接, 减少了获取、 回收连接的耗时

注意事项:

使用上面的情况, 可能会导致其他异常情况, 比如使用到了多数据源,

因为只会获取一次连接; 方法内部的查询不会在去获取连接, 无法获取到其他数据源

如果使用到主从库, 需要注意只读事务是不是走了主库, 如果是则需要考虑解决方法或者不使用只读事务

x6Ad6e.png

Spring 事务管理之只读事务

没有使用只读事务, 同一个SQL, 是可以查询到其他事务提交的最新数据

扩展

不使用只读事务的方式, 使用单条连接, 共用一个SQLsession

@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
  ExecutorType executorType = this.properties.getExecutorType();
  if (executorType != null) {
    return new SqlSessionTemplate(sqlSessionFactory, executorType);
  } else {
    return new SqlSessionTemplate(sqlSessionFactory);
  }
}

自定义SqlSessionTemplate, 改造 SqlSessionInterceptor 中的获取会话方法, 当事务中获取到的会话为空, 尝试线程变量获取或者其他方式!!!
还需要考虑如何关闭会话!!!

1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

懵懵懂懂程序员

如果节省了你的时间, 请鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值