架构师技能9-深入mybatis:Creating a new SqlSession到查询语句耗时特别长

开篇语录:以架构师的能力标准去分析每个问题,过后由表及里分析问题的本质,复盘总结经验,并把总结内容记录下来。当你解决各种各样的问题,也就积累了丰富的解决问题的经验,解决问题的能力也将自然得到极大的提升。

励志做架构师的撸码人,认知很重要,可以订阅:架构设计专栏

      撸码人平时大多数时间都在撸码或者撸码的路上,很少关注框架的一些底层原理,当出现问题时没能力第一时间解决问题,出现问题后不去层层剖析问题产生的原因,后续也就可能无法避免或者绕开同类的问题。因此不要单纯做Ctrl+c和Ctrl+V,而是一边仰望星空(目标规划),一边脚踏实地去分析每个问题。
 

一、背景


       我们最近在使用mybatis执行批量数据插入,数据插入非常慢:每批次5000条数据大概耗时在3~4分钟左右。架构师的职责之一是疑难技术点攻关:要主动积极解决系统出现的问题,过后由表及里分析问题的本质,复盘总结经验,并把总结内容记录下来分享给团队,确保后续如何智慧地绕开同类问题。

以下是排查问题的过程和思路:

二、定位问题


1、全面打印日志:

日志是排查问题的第一手资料。

logback设置mybatis相关日志打印:

<logger name="org.mybatis.spring" level="DEBUG"/>
<logger name="org.apache.ibatis" level="DEBUG"/>
<!--    <logger name="java.sql.PreparedStatement" level="DEBUG"/>-->
<!--    <logger name="java.sql.Statement" level="DEBUG"/>-->
<!--    <logger name="java.sql.Connection" level="DEBUG"/>-->
<!--    <logger name="java.sql.ResultSet" level="DEBUG"/>-->

2、初步定位问题

发现Creating a new SqlSession到查询语句耗时特别长:

     

3、初步排查问题:

有几个可能的原因导致创建新的SqlSession到查询语句耗时特别长:

1. 数据库连接池问题:如果连接池中没有空余的连接,则创建新的SqlSession时需要等待连接释放。可以通过增加连接池大小或者优化查询语句等方式来缓解该问题。

排除连接池问题:我们连接池比较大,通过mysql show processlist查看几乎没有慢查询的连接。

2. 网络延迟问题:如果数据库服务器和应用服务器之间的网络延迟较大,则创建新的SqlSession时会受到影响。可以通过优化网络配置或者将数据库服务器和应用服务器放在同一台机器上等方式来缓解该问题。

排除网络问题:ping mysql地址,耗时都在0.5ms左右。

3. 查询语句过于复杂:如果查询语句过于复杂,则会导致查询时间较长。可以通过优化查询语句或者增加索引等方式来缓解该问题。

排除复杂sql问题:简单insert 语句,通过mysql show processlist查看没有慢查询的连接。

<insert id="batchInsertDuplicate">INSERT INTO b_table_#{day} (<include refid="selectAllColumn"/>) VALUES<foreach collection="list" item="item" index="index" separator=",">(#{item.id ,jdbcType=VARCHAR },#{item.sn ,jdbcType=VARCHAR },#{item.ip ,jdbcType=VARCHAR },.....#{item.createTime ,jdbcType=TIMESTAMP },#{item.updateTime ,jdbcType=TIMESTAMP })</foreach>ON DUPLICATE KEY UPDATE`ip`=VALUES(`ip`),`updateTime`=VALUES(`updateTime`)
</insert>

4. 数据库服务器性能问题:如果数据库服务器性能较低,则创建新的SqlSession时会受到影响。可以通过优化数据库服务器配置或者升级硬件等方式来缓解该问题。

排除数据库服务器性能问题:mysql是8核16G,通过mysql show processlist查看没有慢查询的连接。

5. 应用服务器性能问题:如果应用服务器性能较低,则创建新的SqlSession时会受到影响。可以通过优化应用服务器配置或者升级硬件等方式来缓解该问题。

暂时无法确定:top查看cpu占用比较高90%,可能原因是mybatis框架处理sql语句引起cpu飙高。

三、定位cpu飙高耗时的方法


1、优化代码:

 5000条改为500条批量插入,查看每个线程的耗时依然很高,说明是mybatis框架处理sql语句耗cpu。

top -H -p  18912

2、使用arthas定位:

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar  pid 

使用dashboard可以查看每个线程耗cpu情况,和top -H 差不多:

3、trace方法耗时:

trace com.xxxx.class xxxmethod

逐步跟进去:

最后定位方法

 org.apache.ibatis.parsing.GenericTokenParser:parse耗时:

查看 org.apache.ibatis.parsing.GenericTokenParser:parse的源码:

public String parse(String text) {StringBuilder builder = new StringBuilder();if (text != null) {String after = text;int start = text.indexOf(this.openToken);for(int end = text.indexOf(this.closeToken); start > -1; end = after.indexOf(this.closeToken)) {String before;if (end <= start) {if (end <= -1) {break;}before = after.substring(0, end);builder.append(before);builder.append(this.closeToken);after = after.substring(end + this.closeToken.length());} else {before = after.substring(0, start);String content = after.substring(start + this.openToken.length(), end);String substitution;if (start > 0 && text.charAt(start - 1) == '\\') {before = before.substring(0, before.length() - 1);substitution = this.openToken + content + this.closeToken;} else {substitution = this.handler.handleToken(content);}builder.append(before);builder.append(substitution);after = after.substring(end + this.closeToken.length());}start = after.indexOf(this.openToken);}builder.append(after);}return builder.toString();}

 主要作用是对 SQL 进行解析,对转义字符进行特殊处理(删除反斜杠)并处理相关的参数(${}),如sql需要解析的标志${name} 替换为实际的文本。我们可以使用一个例子说明:

final Map<String,Object> mapper = new HashMap<String, Object>();
mapper.put("name", "张三");
mapper.put("pwd", "123456");//先初始化一个handler
TokenHandler  handler = new TokenHandler() {@Overridepublic String handleToken(String content) {System.out.println(content);return (String) mapper.get(content);}};
GenericTokenParser parser = new GenericTokenParser("${", "}", handler);
System.out.println("************" + parser.parse("用户:${name},你的密码是:${pwd}"));

通过源码发现,如果mapper定义的字段很多,for遍历条数比较大(下面红色部分):

<insert id="batchInsertDuplicate">
        INSERT INTO b_table_#{day} (
        <include refid="selectAllColumn"/>
        ) VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (
            #{item.id ,jdbcType=VARCHAR },
            #{item.sn ,jdbcType=VARCHAR },
            #{item.ip ,jdbcType=VARCHAR },
            .....
            #{item.createTime ,jdbcType=TIMESTAMP },
            #{item.updateTime ,jdbcType=TIMESTAMP }
            )
        </foreach>

        ON DUPLICATE KEY UPDATE
        `ip`=VALUES(`ip`),
        `updateTime`=VALUES(`updateTime`)
</insert>

需要解析耗时较久,由于都是字符串遍历,特别耗CPU,因此可以看到cpu飙升很高。

四、解决


解决:直接执行原声sql。

不使用mapper方式拼接sql,而是手动拼接好sql,使用JdbcTemplate执行原声sql。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2803762.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

操作系统--调度算法

一、进程调度算法&#xff08;CPU调度算法&#xff09; 什么时候会发生 CPU 调度呢&#xff1f;通常有以下四种情况&#xff1a; 「抢占式调度」&#xff1a;进程正在运行的时&#xff0c;可以被打断&#xff0c;使其把 CPU 让给其他进程。那抢占的原则一般有三种&#xff0c…

测试用例设计方法:招式组合,因果判定出世

1 引言 上篇讲了等价类划分和边界值分析法&#xff0c;而这两种方法只考虑了单个的输入条件&#xff0c;并未考虑输入条件的各种组合、输入条件之间的相互制约关系的场景。基于此短板&#xff0c;因果图法和判定表法应运而生。 2 因果图法 2.1 概念及原理 2.1.1 定义 一种…

BLEU: a Method for Automatic Evaluation of Machine Translation

文章目录 BLEU: a Method for Automatic Evaluation of Machine Translation背景和意义技术原理考虑 n n n - gram中 n 1 n1 n1 的情况考虑 n n n - gram中 n > 1 n\gt 1 n>1 的情况考虑在文本中的评估初步实验评估和结论统一不同 n n n 值下的评估数值考虑句子长度…

一文了解L7812CV的引脚图介绍、参数解读

L7812CV简介 L7812CV是一款具有稳压功能的正向型线性稳压器&#xff0c;能够将输入电压稳定输出为12V的直流电压。它适用于各种需要12V电源的电子设备、电路和系统。 引脚图介绍 L7812CV有三个引脚&#xff0c;分别为输入引脚&#xff08;输入电压Vin&#xff09;、地引脚&…

什么是智慧公厕?智慧公厕跟传统公共厕所的区别

智慧公厕是近年来新兴起的一种公共设施&#xff0c;通过物联网技术的应用&#xff0c;实现了公厕的全面感知、全时监测、全方位精细化管理。与传统的公共厕所相比&#xff0c;智慧公厕在许多方面带来了翻天覆地的变化。本文以智慧公厕源头厂家广州中期科技有限公司&#xff0c;…

【2024.02.22】定时执行专家 V7.0 发布 - TimingExecutor V7.0 Release - 龙年春节重大更新版本

目录 ▉ 新版本 V7.0 下载地址 ▉ V7.0 新功能 ▼2024-02-21 V7.0 - 更新日志▼ ▉ V7.0 新UI设计 ▉ 新版本 V7.0 下载地址 BoomWorks软件的最新版本-CSDN博客文章浏览阅读10w次&#xff0c;点赞9次&#xff0c;收藏41次。▉定时执行专家—毫秒精度、专业级的定时任务执行…

【计算机网络】一些乱七八糟内容

MAC Media Access Control 用于在局域网&#xff08;LAN&#xff09;或广域网&#xff08;WAN&#xff09;中实现设备自动接入网络 "载波侦听多路访问"(Carrier Sense Multiple Access) CSMA/CD 是CSMA的升级版本&#xff0c;加入了序列号检测机制。 CSMA/CA 是CSM…

最优传输(Optimal Transport)

最优传输&#xff08;Optimal Transport&#xff09;是一种数学理论和计算方法&#xff0c;用于描述两个概率分布之间的距离或者对应关系。它的核心概念是如何以最佳方式将一组资源&#xff08;如质量、能量等&#xff09;从一个位置传输到另一个位置。 基本概念&#xff1a; …

金和OA UploadFileBlock接口任意文件上传漏洞

声明 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任 1. 产品简介 金和数字化智能办公平台&#xff08;简称JC6&#xff09;是…

Shopee平台玩具类目选品策略大揭秘

在Shopee平台上经营玩具类目&#xff0c;对于卖家来说&#xff0c;选品是至关重要的一环。只有通过精准的选品策略&#xff0c;才能在激烈的市场竞争中脱颖而出&#xff0c;提高产品的曝光度和销售业绩。以下是一些有效的选品策略&#xff0c;帮助卖家在Shopee平台上成功经营玩…

springboot210基于Springboot开发的精简博客系统的设计与实现

基于Springboot开发的精简博客系统的设计与实现 摘要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。以前企业对于博客信息的管理和控制&#xff0c;采用人工登记的方式保存相关数据&#…

北斗卫星技术引领智能穿戴:未来鞋履的革命

北斗卫星技术引领智能穿戴&#xff1a;未来鞋履的革命 在福建莆田市的苍然社区&#xff0c;70岁以上老人和特殊群体共400多人领到了社区免费发放的北斗定位鞋&#xff0c;该鞋内置北斗导航芯片&#xff0c;具有多种定位、足迹查询、超出范围主动报警等功能。老人穿上这双鞋&am…

[DP学习] 期望DP

一般思路 注&#xff1a;可以用方差求平方的期望 例题一 思路 重点&#xff1a;如何设状态&#xff0c;如何转移。 设状态 f[i] i 张能买到不同卡片的种类数的期望值&#xff08;直接对问题设置状态&#xff09; 状态转移&#xff1a;由于从f[i1]转移到 f[i] 时&#xff0…

Android相机调用-libusbCamera【外接摄像头】【USB摄像头】 【多摄像头预览】

有的自定义系统&#xff0c;对于自己外接的USB摄像头&#xff0c;android原生的camera和camera2都无法打开&#xff0c;CameraX也用不了。这时候就要用libusbCamera&#xff0c;这个库可以打开摄像头&#xff0c;还可以多摄像头同时预览。本文主要是同时打开3个USB摄像头的项目…

LabVIEW多场景微振动测试平台与教学应用

LabVIEW多场景微振动测试平台与教学应用 在多种工程实践中&#xff0c;微振动的测试与分析对于评估结构的稳定性及其对环境的影响至关重要。针对这一需求&#xff0c;开发了一套基于NI-cDAQ和LabVIEW的多场景微振动测试平台&#xff0c;提高微振动测试的精确度与灵活性&#x…

ArcgisForJS如何使用ArcGIS Server发布的切片地图服务?

文章目录 0.引言1.准备海量地理数据2.ArcGIS Server发布切片地图服务3.ArcgisForJS使用ArcGIS Server发布的切片地图服务 0.引言 ArcGIS Server是一个由Esri开发的地理信息系统&#xff08;GIS&#xff09;服务器软件&#xff0c;它提供了许多功能&#xff0c;包括发布切片地图…

Kotlin 进阶 学习 委托

1.接口委托 package com.jmj.jetpackcomposecompositionlocal.byStudy/*** 接口委托*/ interface HomeDao{fun getAllData():List<String> }interface ADao{fun getById(id:Int):String }class HomeDaoImpl:HomeDao{override fun getAllData(): List<String> {ret…

嵌入式学习笔记总结Day23----minshell项目总结

今天进行了linux系统高级编程io阶段学习的结尾&#xff0c;完成了一个minshell的小项目。 一、项目介绍 利用Linux中IO接口实现MiniShell&#xff0c;实现常用的shell指令的实现。 项目想要实现需要思考的地方有&#xff1a; 1.如何打印终端命令 2.如何接受终端命令 3.实现对…

windows前后端项目部署

装好windows虚拟机 1.远程连接 计算机右击属性&#xff0c;高级防火墙设置&#xff0c;远程连接服务允许 2.安装jdk,tomcat&#xff0c;解压工具 把安装包拖进去 双击安装解压软件 jdk安装 双击安装 配置环境变量&#xff08;复制jdk路径&#xff09; 计算机右击属性高级…

苹果分拣检测YOLOV8NANO

苹果分拣&#xff0c;可以检测成熟、切片、损坏、不成熟四种类型&#xff0c;YOLOV8NANO&#xff0c;训练得到PT模型&#xff0c;然后转换成ONNX&#xff0c;OPENCV的DNN调用&#xff0c;支持C,PYTHON 苹果分拣检测YOLOV8NANO&#xff0c;检测四种类型苹果