记一次数据批量插入实践

news2024/11/26 4:30:08

背景:

        2023月7月份入职新公司,初来乍到还没参入到具体的项目中,技术负责人安排写一个批量处理数据的服务,于是便有了以下文章。

        数据流程大概是这样,从clickhouse表中获取数据,并从elasticserach中根据业务序号增加若干属性,批量保存到mysql中,最后再更新clickhouse中数据状态为已生成。

        本文以10000条数据示例(本机环境 docker(mysql+clickhouse)、es测试服务器环境)。

思考:

        很简单的处理流程,刚参加工作的时候这样的服务写过很多次(jdbc Class.forName Connection PreparedStatment Resulset一些列操作),顺手拈来的事情。

  • 技术框架:springboot+mybatis plus+spring data elasticserach + dynamic datasource
  • 实现思路:
  1. orm框架选择mybatis处理mysql和clickhouse,使用mybatis plus封装好的saveOrUpdateBatch方法省得自己写sql,
  2. 使用spring data elasticserach封装好的方法进行es查询;
  3. 要同时操作clickhouse和mysql并且需要支持事务,选择dynamic datasource;       

        和相关同事沟通每天的数据量大概在5-6K(这里解释下数据量为什么自己不去看,内网环境需要vpn,刚入职暂未分配账号),于是开始了编码工作。

过程实践:

        定义方法:

         

        1、生成保存到mysql的数据;

                1.1、clickhouse批量查询数据;

                1.2、查询数据结果根据业务编号从es中查询数据信息;

                1.3、2个结果合并属性并生成mysql入库对象集合。

                部分代码:                        

public List<QcBaseDataInfo> generate(String day, int limit) {
        /**
         * 1、从clickhouse取昨日数据
         * 2、从es中取数据(根据序列号)
         * 3、封装智能质检数据
         */
        Assert.notNull(day, "业务数据日期不允许为空");
        List<ChWicDataInfo> chWicDataInfos = queryFormCh(day, limit);
        List<QcBaseDataInfo> qcBaseDataInfoList = getPropertiesFromEs(chWicDataInfos);
        return qcBaseDataInfoList;
    }

@Override
public List<ChWicDataInfo> queryFormCh(String day, int limit) {
        Assert.notNull(day, "业务数据日期不允许为空");
        List<ChWicDataInfo> queryResult = chWicDataInfoService.list(new QueryWrapper<ChWicDataInfo>().lambda()
                .eq(ChWicDataInfo::getAcctDay, day)
                .eq(ChWicDataInfo::getIsDown, STATUS_ASR_DEAL_FINISHED)
                .eq(ChWicDataInfo::getHadToDataLake, false)
                .last(" limit " + limit));
        return queryResult;
    }

@Override
public List<QcBaseDataInfo> getPropertiesFromEs(List<ChWicDataInfo> chWicDataInfos) {
        List<String> serialNumbers = new ArrayList<>();
        chWicDataInfos.forEach(q -> {
            serialNumbers.add(q.getId());
        });
        log.info("start query serialNumbers:{} from es", serialNumbers);
        List<EsWicDataInfo> esWicDataInfos = esWicDataRepository.findBySerialNumberIn(serialNumbers);
        log.info("query from es end...");
        List<QcBaseDataInfo> qcBaseDataInfoList = construct(chWicDataInfos, esWicDataInfos);
        return qcBaseDataInfoList;
    }

        2、数据批量保存/更新到mysql中;

                部分代码:                

@Override
 public boolean saveOrUpdateBatch(List<QcBaseDataInfo> data) {
        boolean result = qcBaseDataInfoService.saveOrUpdateBatch(data, BATCH_SIZE);
        return result;
 }

        3、clickhouse中更新数据状态为已更新;

                部分代码:           

本地测试后放到生产环境执行,发现5万多数据2个多小时才执行完,纳尼,不能够啊。

于是开始想问题出在了那里,开始认为可能是es查询费事,经测试后无问题;

batchSize(原设置为2000)设置的过大?测试后亦无问题;

自始至终就没想过是mybatis plus的批量更新updateBatchById的问题。

一直找不到问题于是便开始了分步骤测试。 

分步骤测试:

        思路:针对每步操作进行测试,排查用时过长的操作。        

  • mysql保存 10000条 batchSize=1024

        批量保存用时:saveBatch 23s

        批量保存或更新用时:saveOrUpdateBatch 111s

  • mysql保存+clickhouse更新 10000条 batchSize=1024

        批量保存用时:saveBatch 600s

        批量保存或更新用时:saveOrUpdateBatch 未测试

  • mysql保存+clickhouse更新 10000条 batchSize=1024 替换mybatis plus updateBatchById 为 update table set column={value} where id in ({ids})

        批量保存用时:saveBatch 22s

        批量保存或更新用时:saveOrUpdateBatch 180S

        生产环境每天的数据量约60k/每天,现每天约18分钟处理完成,执行效率提高了好几个数量级。

        排查到是mybatis plus的updateBatchById耗时过长,查看了源代码是批量执行,不知道为啥这么慢。

        mybatis plus updateBatcheById源代码: 

        

总结:

        一次小事情反应出一个大问题,想当然的以为框架封装的方法肯定是最优的,加上经验使然导致了本次问题,以下一句话可总结,分享。

        纸上得来终觉浅,觉知此事要躬行。

        纸上得来终觉浅,觉知此事要躬行。

        纸上得来终觉浅,觉知此事要躬行。

本文完。

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

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

相关文章

【VALSE2023】0610 邓成/杨二昆《多模态融合感知年度进展综述》

from&#xff1a; https://www.bilibili.com/video/BV1YP411t73r 文章目录 多模态融合感知理论多模态预训练模型多模态感知理解多模态内容生成 总结和展望 多模态融合感知理论 多模态预训练模型 多模态感知理解 多模态内容生成 总结和展望

flink如何监听kafka主题配置变更

背景&#xff1a; 从前一篇文章我们知道flink消费kafka主题时是采用的手动assign指定分区的方式&#xff0c;这种消费方式是不处理主题的rebalance操作的&#xff0c;也就是消费者组中即使有消费者退出或者进入也是不会触发消费者所消费的分区的&#xff0c;那么疑问就来了&am…

用户的管理

一、用户的管理 useradd、usermod、userdel 二、用户组的管理 groupadd、groupmode、groupdel 三、用户登录情况查看 w可以看用户操作 其他可以看用户ip 四、用户的提权&#xff08;重点&#xff09; 三种方法&#xff1a;1、su - 用户名&#xff08;需要该用户名的密码&a…

Pandas 的Merge函数详解

在日常工作中&#xff0c;我们可能会从多个数据集中获取数据&#xff0c;并且希望合并两个或多个不同的数据集。这时就可以使用Pandas包中的Merge函数。在本文中&#xff0c;我们将介绍用于合并数据的三个函数 merge、 merge_ordered、 merge_asofmerge merge函数是Pandas中…

Kotlin~Mediator中介者模式

概念 创建一个中介来降低对象之间的耦合度&#xff0c;关系”多对多“变为“一对多”。 角色介绍 Mediator&#xff1a;抽象中介者&#xff0c;接口或者抽象类。ConcreteMediator&#xff1a;中介者具体实现&#xff0c;实现中介者接口&#xff0c;定义一个List管理Colleagu…

【频率派和贝叶斯派】进阶学习-贝叶斯方法原理、基本结构、代码构建+图模型

文章目录 前言1.理论支撑贝叶斯思考模式贝叶斯定理贝叶斯公式 2. 应用转化2.1 拼写检查 3. 贝叶斯网络3.1 贝叶斯网络的定义3.2 三个形式和实际案例的构建关系 前言 频率派与贝叶斯派各自不同的思考方式&#xff1a; 1.频率派把需要推断的参数θ看做是固定的未知数&#xff0c…

草图大师su曲面怎么推拉?SketchUp推拉怎么使用?

首先我们需要安装这个推拉插件&#xff0c;然后打开草图大师&#xff0c;打开超级推拉工具栏&#xff0c;可以看到&#xff0c;超级推拉主要有以下几种推拉方式&#xff1a;J联合推拉、R近似值推拉、V矢量推拉、N法线推拉、X挤出推拉、F跟随推拉。 首先选择你要进行推拉操作的物…

【iPhone】手机还有容量,拍视频却提示 iPhone 储存空间已满

文章目录 前言解决方案 结语 前言 今天在用 iPhone 录像的时候突然提醒我 iPhone储存空间已满 你没有足够的储存空间来录制视频” 可我明明还有 20G 的容量 我非常疑惑&#xff0c;因为我之前还剩1个G都能录像&#xff0c;现在20G反而不行了&#xff0c;于是重启了手机&#…

数据结构【哈夫曼树】

哈夫曼树 哈夫曼树的概念哈夫曼树的构造构造算法的实现哈夫曼树应用哈夫曼编码哈夫曼编码的算法实现 哈夫曼树的概念 最优二叉树也称哈夫曼 (Huffman) 树&#xff0c;是指对于一组带有确定权值的叶子结点&#xff0c;构造的具有最小带权路径长度的二叉树。权值是指一个与特定结…

c++ 拷贝构造

我们思考一下这个问题&#xff1a; 观察以下代码&#xff0c;在运行的时候会崩溃 想一想为什么 #include<iostream> using namespace std;//栈类 typedef int DataType; class Stack { public://默认构造&#xff1a;Stack(size_t capacity 3){_array (DataType*)ma…

在广告宣传领域,PS透明屏有哪些优点表现?

PS透明屏是一种新型的显示技术&#xff0c;它将传统的显示屏幕与透明材料相结合&#xff0c;使得屏幕能够同时显示图像和透过屏幕看到背后的物体。 这种技术在商业展示、广告宣传、产品展示等领域有着广泛的应用前景。 PS透明屏的工作原理是利用透明材料的特性&#xff0c;通…

iTOP-i.MX8MM开发板添加 isb 转串口设备驱动

对于通过 USB 接口访问的模块&#xff0c;在 Linux 内核中集成 USB 驱动程序。我们需要配置内核选中支持 GSM 和 CDMA 模块的 USB 转串口驱动 > Device Drivers -> USB support (USB_SUPPORT [y]) -> USB Serial Converter support (USB_SERIAL [y]) -> USB dr…

计算机网络(7) --- UDP协议和TCP协议

计算机网络&#xff08;6&#xff09; --- https协议_哈里沃克的博客-CSDN博客https协议https://blog.csdn.net/m0_63488627/article/details/132112683?spm1001.2014.3001.5501 目录 1.补充知识 1.PORT端口号 2.端口号范围划分 3.知名端口号 2.UDP协议 1.UDP报头 2.U…

EVE-NG MPLS 静态 LSP

1 拓扑 2 配置步骤 2.1 配置接口IP 和路由 LER1 interface GigabitEthernet1/0ip address 10.1.1.1 255.255.255.0quitinterface GigabitEthernet2/0ip address 11.1.1.1 255.255.255.0quitip route-static 21.1.1.0 24 10.1.1.2VPC1 ip 11.1.1.100/24 11.1.1.1 配置完成后…

LeetCode--HOT100题(22)

目录 题目描述&#xff1a;160. 相交链表&#xff08;简单&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;160. 相交链表&#xff08;简单&#xff09; 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表…

gradle项目Connection timed out,build时先下载gradle问题download gradle-x.x-bin.zip

IDEA 导入 Gradle 项目&#xff0c;编译的时候会默认下载 配置版本的Gradle.zip问题&#xff0c;一般会下载失败&#xff0c;提示Connection timed out&#xff0c;连接超时。 解决办法&#xff1a; 修改项目根目录下gradle目录下的gradle-wrapper.properties文件&#xff0c;…

小红书投放复盘怎么做,达人流量统计

作为众多品牌进行产品宣推与传播的重要阵地&#xff0c;红薯一直以来都备受关注。而随着平台投放成本的水涨船高&#xff0c;如何优化投放结果&#xff0c;就成了关键问题。所以&#xff0c;今天就来分享一下&#xff0c;小红书投放复盘怎么做&#xff0c;达人流量统计&#xf…

《操作系统真象还原》学习笔记:第六章 完善内核

一.函数调用约定简介 调用约定&#xff0c;calling conventions&#xff0c;从字面上理解&#xff0c;它是调用函数时的一套约定&#xff0c;是被调用代码的接口&#xff0c;它体现在&#xff1a; 参数的传递方式&#xff0c;是放在寄存器中&#xff1f;栈中&#xff1f;还是…

JavaSE知识点整理---集合篇

文章目录 1、数组与集合的区别?2、List、Set、Map的区别&#xff1f;3、ArrayList、LinkedList、Vector的区别&#xff1f;4、Java集合的快速失败机制【fail-fast】5、List接口常用方法6、List的三种遍历方式 1、数组与集合的区别? 在Java中&#xff0c;数组和集合都是容器&a…

如何使用 reqwest 包

GET 请求 向连接发起一个 GET 请求&#xff1a;https://hacker-news.firebaseio.com/v0/topstories.json&#xff0c;并解析返回的内容。 尝试发起请求 因为是 GET 请求&#xff0c;可以先在浏览器中进行查看&#xff0c;浏览器可以正常显示一个 id 列表&#xff0c;如下所示…