记一次mybatis性能问题分析过程
说明
今天发现个2个问题,一是mybatisplus执行一条某个字段值比较长(约1.8M的文本)的INSERT语句耗时要90s+;二是读取这个1.8M文本返回给前端耗时6min。查查查查了半天搞不清楚什么原因,最后在同事过来分析指点下立马解决。突然觉得自己像个沙比,特此记录,知耻后勇。另外也反思一下在查问题过程中的思路和方式问题。
问题1
现象
INSERT耗时过长
如图,SQL是单条记录更新,只不过第二个String比较大。下面是打印的耗时
当时分析思路
- 想验证一下此条INSERT语句通过navicat执行需要多长时间?
复制出来执行一下,发现navicat执行需要16s左右,且返回的数据库response显示实际执行2s多。感觉是navicat在执行前后做了些业务操作如分析文本,导致要十几秒 - 验证原生jdbc执行效率
通过原生jdbc执行多次发现执行时间在4s左右,还是相差甚远。开始怀疑是否mybatis是不是做了些文本分析才增加了耗时 - 验证mybatis的代理类执行效率
构建了一个最简单的mybatis来执行,效率与jdbc相似也在4s左右,说明并没有 - 是否是事务等待?
通过show processlist 和查询 information_schema.innodb_trx、innodb_locks、innodb_lock_waits发现执行此insert时并没有任何语句在执行,也就是说不存在事务等待 - 开始懵逼?
想不通,看到ExecuteTime 139ms,觉得可能是mybatis里面哪个方法有问题,开始疯狂debug,不停debug,业务代码弄一下,mybatis源码弄一下,真的懵逼 - 寻求支援
在同事的提示下猜测可能是打印日志拼接了过长的字符串所以耗时增加,原项目的日志等级不管怎么调,mybatis都在输出执行sql,无奈用回上面的 3 中的mybatis测试程序,将日志等级调整为ERROR,发现不输出日志和输出日志时间差异并不大,在10ms左右!然后我就放弃了思考。。。
后续解决
让同事过来帮忙一起看,他对于这个项目更熟悉,所以直接找到了mybatisplus的配置类,发现了一个PerformanceInterceptor,如下
此类中会打印执行的sql,难怪原项目怎么调日志等级都没用,原来在这里打印的
然后将此bean注释掉重新尝试一遍,那条执行时间长的 INSERT 立马丝滑,1s内就执行完成了。于是将此 bean 添加 @Profile("localdev") 注解,只在本地测试环境开启。
将代码提交后构建uat环境验证,结果无误,至此解决。
后续研究
本来想在本机复现,发现 PerformanceInterceptor 正常配置下只会打印 预编译sql,如下图
这样执行效率并没有受到影响,看来是某个实现将参数替换预编译中?的功能导致的低效问题。
这个替换功能目前网上主要是说要将log-impl设置为 StdOutImpl,但是尝试过无效,后续还是要找时间看看,不过可以不用太过纠结,毕竟这只是某个框架的配置的东西。
问题2
现象
1.8M左右的文本文件,将内容读取后以String返回,返回效率低花了6分钟。
分析过程
- 对比分析
首先还是尝试用一个测试的Springboot项目来返回此文本文件,以判断是否是网络或者其他原因。
测试结果发现相应速度很快,在200ms内。即使加大文本量到18M,相应时间也在700多ms,所以不是框架或者网络等原因。 - 怀疑是filter或者interceptor或者AOP处理response耗时过长
项目内自定义的AOP过了一遍都没什么特别的处理。有两个自定义的与保留用户登录状态的token相关的filter,在他们的 chain.doFilter(request,response)方法前和该filter的 doFilter方法结尾都
打印时间,发现第一个filter的start 和 end 隔得特别长,但是这个filter根本没做什么处理,就是一个 Map.remove的操作,所以肯定是有别的我没发现的filter在作怪。 - 交给其他同事
由于对这块配置包括springSecurty不熟,并且还有别的项目要开发,项目经理建议交给其他同事来查此问题。
后续解决
是fastjson中对于web框架的传参出参做了处理,导致慢的。
后续研究
tomcat中注册了哪些filter可以通过 chain 这个对象来看
总结
- 最后回头来看,其实我对于问题的分析思路基本上都是正确的,就差在熟悉程度上,对于框架的操作使用,问题排查还是需要多写多练才能提升经验。
- 不要被情绪影响,在查问题很大一部分影响因素是心态和情绪。当时的情况是有另一个项目需要开发,前端要找我对接;并且现场部署的产品有问题,报障群其他人都在装死;这个性能问题昨天已经解了一天,解决完部分问题后又冒出了这些新问题;
这三连击加起来让我在不同的项目中来回切换,并且产生了焦躁情绪,甚至在怀疑自己,这些都会阻碍思考。 - 后续做事要分清轻重缓急,并且心态要放平和,用观察者心态来处理情绪。还需要多积累分析解决问题的实际经验,分析问题中不要死磕去debug。
至此
记一次mybatis性能问题分析过程的更多相关文章
- 记一次Java Core Dump分析过程
#背景提要 很久没有亲自动手部署代码了,命令行的亲切感越来越低.放飞了键盘,习惯了鼠标操作的windows环境.冷不丁实操部署也是不错的. 常常在部署时,运维同学对于[hs_err_pid]文件视而不 ...
- mybatis源码分析(五)------------SQL的执行过程
在对SQL的执行过程进行分析前,先看下测试demo: /** * @author chenyk * @date 2018年8月20日 */ public class GoodsDaoTest { pr ...
- MyBatis 源码分析 - SQL 的执行过程
* 本文速览 本篇文章较为详细的介绍了 MyBatis 执行 SQL 的过程.该过程本身比较复杂,牵涉到的技术点比较多.包括但不限于 Mapper 接口代理类的生成.接口方法的解析.SQL 语句的解析 ...
- MyBatis 源码分析 - 映射文件解析过程
1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...
- MyBatis 源码分析 - 配置文件解析过程
* 本文速览 由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括.本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settings,typeAl ...
- 使用Django.core.cache操作Memcached导致性能不稳定的分析过程
使用Django.core.cache操作Memcached导致性能不稳定的分析过程 最近测试一项目,用到了Nginx缓存服务,那可真是快啊!2Gb带宽都轻易耗尽. 不过Api接口无法简单使用Ngin ...
- 性能测试——记XX银行保全项目性能问题分析优化
记XX银行保全项目性能问题分析优化 数据库问题也许是大部分性能问题的关注点,但是JAVA应用与数据库交互的关节,JDBC 就像是我们人体的上半身跟下半身的腰椎,支持上半身,协调下半身运动的重要支撑点. ...
- 精尽MyBatis源码分析 - MyBatis 的 SQL 执行过程(一)之 Executor
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- 精尽MyBatis源码分析 - SQL执行过程(二)之 StatementHandler
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- 精尽MyBatis源码分析 - SQL执行过程(三)之 ResultSetHandler
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
随机推荐
- KingbaseES 局部索引
一个列要不要建立btree索引,判断条件是其键值分布是否够离散,比如主键.唯一键,可以建立索引.如果这个列有大量重复的值,则建立索引没有意义. 在生产环境中常会碰到键值分布不均匀的列,如表t1有一个名 ...
- cmake 入门笔记
以下内容为本人的著作,如需要转载,请声明原文链接微信公众号「englyf」https://www.cnblogs.com/englyf/p/16667896.html 1. cmake 是什么? 这些 ...
- 天天写SQL,这些神奇的特性你知道吗?
摘要:不要歪了,我这里说特性它不是 bug,而是故意设计的机制或语法,你有可能天天写语句或许还没发现原来还能这样用,没关系我们一起学下涨姿势. 本文分享自华为云社区<[云驻共创]天天写 SQL, ...
- [Python]-opencv-python模块(cv2)-图片读取和格式转换
python常常用opencv模块来处理图像. import cv2 as cv 读取图片:imread() 默认按照彩色三通道读取: img = cv2.imread(path) 读取灰度图: im ...
- JS作用域、变量提升和闭包
作用域 作用域可以理解为JS引擎执行代码的时候,查找变量的规则. 从确定变量访问范围的阶段的角度,可以分为2类,词法作用域和动态作用域.js是词法作用域. 从变量查找的范围的角度,可以分为3类,全局作 ...
- stm32fxx_hal_i2c.c解读之HAL_I2C_Mem_Write
HAL_I2C_Mem_Write()函数位于stm32fxx_hal_i2c.c文件的2432行,源代码对该函数的解释如下图 HAL_StatusTypeDef HAL_I2C_Mem_Write( ...
- 日志收集工具 Fluentd 使用教程
转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247499829&idx=1&sn=1f92daa88d ...
- Kubernetes 基本概念与组件
Kubernetes(简称 K8S) 的出现是容器化技术发展的必然结果,容器化是应用程序级别的虚拟化,运行单个内核上有多个独立的用户空间实例,这些实例就是容器:容器提供了将应用程序的代码.运行时.系统 ...
- kubeoperator 使用外部mysql
1.导出 kubeoperator 的数据库 sql 文件,然后导入到外部mysql 2.正常关闭 kubeoperator 3.关闭 kubeoperator 不会影响已经部署的 k8s 集群 4. ...
- 查询参数: Query Parameters
官方文档地址: https://fastapi.tiangolo.com/zh/tutorial/query-params/ # -*- coding: UTF-8 -*- from fastapi ...