mybatisplus,jdbc 批量插入

1.测试用例
项目中遇到在做导入号码的时候我们会用到批量导入,提高入库的速度。接下来我们以10000条为测试用例。
1.1 批量执行sql语句
当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率
JDBC的批量处理语句包括下面三个方法:
- addBatch(String):添加需要批量处理的SQL语句或是参数;
- executeBatch():执行批量处理语句;
- clearBatch():清空缓存的数据
通常我们会遇到两种批量执行SQL语句的情况:
- 多条SQL语句的批量处理;
- 一个SQL语句的批量传参;
1.2 导入excell
2.先使用mybatisplus的批量插入
phoneListService.saveBatch(callLists);

感觉插入还是有些慢,查了下文档,需要增加一个参数
Postgres jdbc的连接:
url: jdbc:postgresql://102.2.1.21:5432/postgres?
binaryTransfer=false&forceBinary=false&reWriteBatchedInserts=true
Mysql jdbc连接:
jdbc:mysql://102.2.1.21:3306/demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B1&rewriteBatchedStatements=true
增加以下的参数进行优化
rewriteBatchedStatements=true:控制是否将批量插入语句转换成更高效的形式,true表示转换,默认为false
binaryTransfer=false:控制是否使用二进制协议传输数据,false表示不适用,默认为true。
forceBinary=false:控制是否将非 ASCII 字符串强制转换为二进制格式,false表示不强制转换,默认为true

3.用jdbc插入
感觉还是慢,不过不知道是什么原因。后来该用jdbc原生的,每500提交一次
Connection conn = jdbcUtils.getConnection();PreparedStatement ps = null;try {ps = jdbcUtils.createPreparedStatement1(conn, sql);//取消自动提交conn.setAutoCommit(false);for (int i = 0; i < phoneList.size(); i++) {PhoneList call = phoneList.get(i);Long startTime = DateUtils.getSec("00:00");String date1 = phone.getTodayBegin();String date2 = phone.getTodayStop();logger.warn("======date1:{} date2:{}", date1, date2);if (StringUtil.isNotEmpty(date1)) {startTime = DateUtils.getSec(date1.substring(date1.indexOf(":") - 2));}long endTime = DateUtils.getSec("23:58");if (StringUtil.isNotEmpty(date2)) {endTime = DateUtils.getSec(date2.substring(date2.indexOf(":") - 2));}logger.warn("======startTime:{} endTime:{}", startTime, endTime);if (StringUtils.isNotEmpty(sql)) {String startTimeParam = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, phone.getStartTime());String endTimeParam = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, phone.getEndTime());ps = jdbcUtils.createPreparedStatement2(ps, call.getId(), 2, 1, 0, phone.getRetryCount(), startTime, endTime,112, call.getId(), 0, phone.getPrefix() + call.getCustomerPhone(), 1, phone.getPrefix() + call.getCustomerPhone(),1, phone.getName(), 101, phone.getCampaignId(), phone.getMark(), phone.getIvrProfileUrl(), startTimeParam, endTimeParam);}ps.addBatch();if (i % 500 == 0) {ps.executeBatch();ps.clearBatch();}}ps.executeBatch();ps.clearBatch();//所有语句都执行完毕后才手动提交sql语句conn.commit();} catch (SQLException e) {logger.error("insertBatchSql error:{}", e);} finally {jdbcUtils.close(conn, ps);}
jdbcutils工具,也可以自己实现
package com.gary.utils.jdbc;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;/*** JDBC工具类** @author byx*/
public class JdbcUtils {private final ConnectionManager connManager;private static Logger logger = LoggerFactory.getLogger(JdbcUtils.class);/*** 创建JdbcUtils** @param dataSource 数据源*/public JdbcUtils(DataSource dataSource) {connManager = new ConnectionManager(dataSource);}public Connection getConnection() {return connManager.getConnection();}public void close(Connection conn, PreparedStatement stmt) {connManager.close(conn, stmt, null);}public PreparedStatement createPreparedStatement1(Connection conn, String sql) throws SQLException {PreparedStatement stmt = conn.prepareStatement(sql);return stmt;}public PreparedStatement createPreparedStatement2(PreparedStatement stmt, Object... params) throws SQLException {for (int i = 0; i < params.length; ++i) {stmt.setObject(i + 1, params[i]);}return stmt;}private PreparedStatement createPreparedStatement(Connection conn, String sql, Object... params) throws SQLException {PreparedStatement stmt = conn.prepareStatement(sql);for (int i = 0; i < params.length; ++i) {stmt.setObject(i + 1, params[i]);}return stmt;}/*** 查询数据库并转换结果集。* 用户可自定义结果集转换器。* 用户也可使用预定义的结果集转换器。** @param sql sql语句* @param resultMapper 结果集转换器* @param params sql参数* @param <T> resultSetMapper返回的结果类型* @return 成功则返回转换结果,失败则抛出DbException,结果为空则返回空列表* @see ResultMapper* @see ListResultMapper* @see SingleRowResultMapper*/public <T> T query(String sql, ResultMapper<T> resultMapper, Object... params) {ResultSet rs = null;PreparedStatement stmt = null;Connection conn = null;try {conn = connManager.getConnection();logger.info("conn:{}", conn);stmt = createPreparedStatement(conn, sql, params);rs = stmt.executeQuery();return resultMapper.map(rs);} catch (SQLException e) {throw new DbException(e.getMessage(), e);} finally {connManager.close(conn, stmt, rs);}}/*** 查询数据库,对结果集的每一行进行转换,然后将所有行封装成列表。* 用户可自定义行转换器。* 用户也可使用预定义的行转换器。** @param sql sql语句* @param rowMapper 行转换器* @param params sql参数* @param <T> rowMapper返回的结果类型* @return 成功则返回结果列表,失败则抛出DbException,结果为空则返回空列表* @see RowMapper* @see BeanRowMapper* @see MapRowMapper* @see SingleColumnRowMapper*/public <T> List<T> queryList(String sql, RowMapper<T> rowMapper, Object... params) {return query(sql, new ListResultMapper<>(rowMapper), params);}/*** 查询数据库,将结果集的每一行转换成JavaBean,然后将所有行封装成列表。** @param sql sql语句* @param type JavaBean类型* @param params sql参数* @param <T> JavaBean类型* @return 成功则返回结果列表,失败则抛出DbException,结果为空则返回空列表*/public <T> List<T> queryList(String sql, Class<T> type, Object... params) {return query(sql, new ListResultMapper<>(new BeanRowMapper<>(type)), params);}/*** 查询数据库,返回结果集中的单个值。* 如果结果集中有多个值,则只返回第一行第一列的值。** @param sql sql语句* @param params sql参数* @param <T> 结果类型* @return 成功则返回结果值,失败则抛出DbException,结果为空则返回null*/public <T> T querySingleValue(String sql, Object... params) {return query(sql, new SingleRowResultMapper<>(new SingleColumnRowMapper<>()), params);}/*** 查询数据库,返回结果集中的单行数据。* 如果结果集中有多行数据,则只返回第一行数据。* 用户可自定义行转换器。* 用户也可使用预定义的行转换器。** @param sql sql语句* @param rowMapper 行转换器* @param params sql参数* @param <T> rowMapper返回的结果类型* @return 成功则返回结果,失败则抛出DbException,结果为空则返回null* @see RowMapper* @see BeanRowMapper* @see MapRowMapper* @see SingleColumnRowMapper*/public <T> T querySingleRow(String sql, RowMapper<T> rowMapper, Object... params) {return query(sql, new SingleRowResultMapper<>(rowMapper), params);}/*** 查询数据库,将结果集中的单行数据转换成JavaBean。** @param sql sql语句* @param type JavaBean类型* @param params sql参数* @param <T> JavaBean类型* @return 成功则返回结果,失败则抛出DbException,结果为空则返回null*/public <T> T querySingleRow(String sql, Class<T> type, Object... params) {return querySingleRow(sql, new BeanRowMapper<>(type), params);}/*** 更新数据库,返回影响行数** @param sql sql语句* @param params sql参数* @return 成功则返回影响行数,失败则抛出DbException*/public int update(String sql, Object... params) {Connection conn = null;PreparedStatement stmt = null;try {conn = connManager.getConnection();stmt = createPreparedStatement(conn, sql, params);return stmt.executeUpdate();} catch (Exception e) {throw new DbException(e.getMessage(), e);} finally {connManager.close(conn, stmt, null);}}/*** 开启事务*/public void startTransaction() {connManager.startTransaction();}/*** 提交事务*/public void commit() {connManager.commit();}/*** 回滚事务*/public void rollback() {connManager.rollback();}/*** 判断当前是否在事务中*/public boolean inTransaction() {return connManager.inTransaction();}
}
Datasource实现
package com.system.modules.utils.jdbc;import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;public class JdbcDataSource {private static Logger logger = LoggerFactory.getLogger(JdbcDataSource.class);// 1. 声明静态数据源成员变量private static DataSource ds;// 2. 创建连接池对象static {logger.info("===数据库初始化====");// 加载配置文件中的数据InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("durid.properties");Properties pp = new Properties();try {pp.load(is);logger.info("===数据库初始化====:{}",pp);// 创建连接池,使用配置文件中的参数ds = DruidDataSourceFactory.createDataSource(pp);} catch (IOException e) {logger.info("===数据库初始化====error:{}",e);} catch (Exception e) {logger.info("===数据库初始化====Exception:{}",e);}}// 3. 定义公有的得到数据源的方法public static DataSource getDataSource() {return ds;}
}
durid.propertes 实现:
driverClassName=org.postgresql.Driver url=jdbc:postgresql://100.2.13.2:5432/postgres?reWriteBatchedInserts=true username=root password=123456 initialSize=5 maxActive=50 maxWait=3000
执行时间:

看着速度快了许多。
4.总结
接下来还要研究下,mybatisplus为什么还是慢。
相关文章:
mybatisplus,jdbc 批量插入
1.测试用例 项目中遇到在做导入号码的时候我们会用到批量导入,提高入库的速度。接下来我们以10000条为测试用例。 1.1 批量执行sql语句 当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库…...
如何使用IP归属地查询API来追踪网络活动
引言 在当今数字化世界中,了解网络活动的源头和位置对于网络安全、市场研究和用户体验至关重要。IP归属地查询API是一种强大的工具,可以帮助您追踪网络活动并获取有关IP地址的重要信息。本文将探讨如何使用IP归属地查询API来追踪网络活动,以…...
【SQL】S0 系列博文大纲
系列博文大纲 SQL 学习环境建议系列博文相关书籍系列博文大纲阶段进展 SQL 学习环境建议 对于 SQL 语言的学习,博主本地使用:MySQL DataGrip; MySQL 提供本地数据库服务; DataGrip IDE,承担编程运行测试任务…...
2023年8月体育用品行业数据分析(京东数据产品)
当前,亚运会临近,这也带动了国民对体育消费的热情,体育产品内销逐渐旺盛,“亚运经济”红利开始显现。鲸参谋数据显示,今年8月份,京东平台上体育用品行业的销量为185万,同比增长2%;销…...
国内高校镜像网站
国内各大高校开源镜像站 排名不分前后 清华大学:https://mirrors.tuna.tsinghua.edu.cn/ 北京大学:https://mirrors.pku.edu.cn/ 北京外国语大学:http:// https://mirrors.bfsu.edu.cn/ 北京理工大学:https://mirrors.bit.e…...
Linux安装kafka-manager
相关链接https://github.com/yahoo/kafka-manager/releases kafka-manager-2.0.0.2下载地址 百度云链接:https://pan.baidu.com/s/1XinGcwpXU9YBF46qkrKS_A 提取码:tzvg 一、安装部署 1.把kafka-manager-2.0.0.2.zip拷贝到目录 /opt/app/elk 2.解压…...
MYSQL索引——B+树讲解
B-/B树看 MySQL索引结构 B-树 B-树,这里的 B 表示 balance( 平衡的意思),B-树是一种多路自平衡的搜索树.它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点。下图是 B-树的简化图. B-树有如下特点: 所有键值分布在整颗树中; 任何一…...
VB将十进制整数转换成16进制以内的任意进制数
VB将十进制整数转换成16进制以内的任意进制数 数值转换,能够将十进制整数转换成16进制以内的任意进制数 Private Function DecToN(ByVal x%, ByVal n%) As StringDim p() As String, y$, r%p Split("0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F", ",")I…...
基于SpringBoot+Vue的宠物领养饲养交流管理平台设计与实现
前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻…...
【图像去噪】【TGV 正则器的快速计算方法】通过FFT的总(广义)变化进行图像去噪(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
windbg调试句柄问题
这里写自定义目录标题 winform,句柄资源不够强,程序crash句柄主程序c程序,加载的插件是c# dll,这时候如何用windbg调试dll库如果查看句柄和对象的关系!handle 怎么能知道哪个句柄是Form对话框的句柄如何查看句柄对应的类对象 winf…...
9月13-14日上课内容 第三章 ELK日志分析系统及部署实例
本章结构 ELK日志分析系统简介 ELK日志分析系统分为 Elasticsearch Logstash Kibana 日志处理步骤 1.将日志进行集中化管理 2.将日志格式化(Logstash) 并输出到Elasticsearch 3.对格式化后的数据进行索引和存储 (Elasticsearch) 4.前端数据的展示(Kibana) Elasticsearch介…...
服务器端应用的安装
前言:相信看到这篇文章的小伙伴都或多或少有一些编程基础,懂得一些linux的基本命令了吧,本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python:一种编程语言&…...
关于硬盘质量大数据分析的思考
近日,看到Backblaze分享了一遍关于硬盘运行监控数据架构的文章,觉得挺有意义的,本文就针对这方面跟大家聊聊。 作为一家在2021年在美国纳斯达克上市的云端备份公司,Backblaze一直保持着对外定期发布HDD和SSD的故障率稳定性质量报告…...
RK3568核心板分区空间不足,如何修改分区大小?
在对评估板进行开发验证时,时常会遇到根目录空间不足的情况,而在其他分区又有冗余空间,这时则需要对分区大小重新进行分配,合理化利用分区空间。 本文将基于HD-RK3568-IOT评估板主要讲解如何修改eMMC分区大小。 1. 分区表介绍…...
Linux系统怎么修改主机名
【微|信|公|众|号:厦门微思网络】 1.备份主机名文件 首先redhat修改主机名,在进行任何修改之前,请务必备份主机名文件。这样,即使出现意外情况,你也能够轻松恢复到原始状态。使用以下命令备份主机名文件࿱…...
BroadcastChannel方法跨浏览器窗口通信
1. 描述 同源 的不同浏览器窗口,Tab 页,frame 或者 iframe 下的不同文档之间可以通过 BroadcastChannel 相互通信。 2. 构造函数 通过 BroadcastChannel 类传入的参数创建实例,传入的参数将指定通道名称,在同源环境下该通道可以…...
山石网科国产化防火墙,打造全方位边界安全解决方案
互联网的快速发展促进了各行各业的信息化建设,但也随之带来了诸多网络安全风险。大部分组织机构采用统一互联网接入方案,互联网出口承担着内部用户访问互联网的统一出口和对外信息服务的入口,因此在该区域部署相匹配的安全防护手段必不可少。…...
AVL 树
文章目录 一、AVL 树的概念二、AVL 树的实现1. AVL 树的存储结构2. AVL 树的插入 一、AVL 树的概念 在 二叉搜索树 中,当我们连续插入有序的数据时,二叉搜索树可能会呈现单枝树的情况,此时二叉搜索树的查找效率为 O(N) 俄罗斯的两位数学家 …...
ggplot2做图(填坑中)
数据 df <- data.frame(x 1:10, y 1:10, f c(rep("A", 5), rep("B", 5))) 做图 1. 散点图 (scatter plot) # scatter plot scatter_plot <- function(df, metadata) {identical(rownames(df), rownames(metadata))data <- cbind(df, metada…...
如何快速掌握91160-cli:面向新手的医院全自动挂号完整指南
如何快速掌握91160-cli:面向新手的医院全自动挂号完整指南 【免费下载链接】91160-cli 健康160全自动挂号脚本,捡漏神器 项目地址: https://gitcode.com/gh_mirrors/91/91160-cli 还在为医院挂号难而烦恼吗?91160-cli是一款专为医疗预…...
3款实用论文降重神器,帮你轻松解决重复率难题
对于正在撰写毕业论文或者期刊论文的创作者来说,重复率不达标绝对是最头疼的问题之一。自己手动改了三五遍,重复率还是卡在要求线以上,不仅耽误时间还影响心态,这时候一款好用的降重工具就能帮你省下不少精力。今天我们就以第三方…...
OpenClaw与Cursor双向集成:打造AI驱动的自动化工作流
1. 项目概述:当OpenClaw遇上Cursor,一个双向赋能的AI大脑诞生如果你正在寻找一种方法,让你在Slack、飞书等协作工具里聊天的同时,能无缝调用一个强大的AI来帮你写代码、查文档、甚至操作GitHub,那么openclaw-cursor-br…...
高性能PDF转SVG矢量转换架构解析:基于Poppler与Cairo的技术实现
高性能PDF转SVG矢量转换架构解析:基于Poppler与Cairo的技术实现 【免费下载链接】pdf2svg A simple PDF to SVG converter using the Poppler and Cairo libraries 项目地址: https://gitcode.com/gh_mirrors/pd/pdf2svg 在数字化文档处理领域,PD…...
当AI学会“看”画质:用Python和PyTorch动手实现一个无参考图像质量评估模型
用Python和PyTorch构建无参考图像质量评估模型:从理论到实践 在数字图像爆炸式增长的时代,图像质量评估(IQA)技术正成为计算机视觉领域不可或缺的一环。无论是社交媒体平台的内容审核、医疗影像的自动分析,还是监控系统的实时画面处理&#x…...
Cursor AI技能库一键部署指南:提升开发效率的标准化配置方案
1. 项目概述:当AI助手Cursor遇上Everything技能库如果你和我一样,日常开发重度依赖Cursor这款AI驱动的IDE,那你肯定也遇到过这样的场景:想让它帮你写个单元测试,得先花几分钟描述TDD流程;想让它重构一段代码…...
AI时代开发者必备:生成式AI应用与核心工程能力双螺旋进阶
1. 项目概述:当AI成为你的新同事最近和几个带团队的朋友聊天,发现一个挺有意思的现象:团队里那些能熟练把AI工具“用起来”的开发者,和那些还在“观望”甚至“抵触”的开发者,在项目交付效率、问题解决深度上ÿ…...
终极游戏串流指南:5步搭建你的个人云端游戏服务器
终极游戏串流指南:5步搭建你的个人云端游戏服务器 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 想要在任何设备上畅玩PC游戏?Sunshine开源游戏串流服务器…...
从零封装Cesium测量工具:我踩过的3个坑和性能优化心得(鼠标事件、坐标拾取、内存泄漏)
从零封装Cesium测量工具:我踩过的3个坑和性能优化心得 第一次在项目中集成Cesium测量工具时,我天真地以为这不过是调用几个API的简单工作。直到用户反馈地图越来越卡、测量结果偶尔出现诡异偏差时,我才意识到自己掉进了多少陷阱。本文将分享三…...
NBTExplorer深度指南:掌握Minecraft数据编辑的完整解决方案
NBTExplorer深度指南:掌握Minecraft数据编辑的完整解决方案 【免费下载链接】NBTExplorer A graphical NBT editor for all Minecraft NBT data sources 项目地址: https://gitcode.com/gh_mirrors/nb/NBTExplorer NBTExplorer是一款专为Minecraft游戏数据设…...

