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…...
Python日志处理器,同时打印到控制台和保存到文件中,并保证格式一致
使用logging模块的时候,默认是输出到控制台的,当然也可以配置输出到文件中,但是当你配置了文件后,控制台的输出就消失了,所以,需要一个策略即能保存到文件中,又能输出到控制台中。 下面是我做的…...
JavaWeb后端开发登录操作 登录功能 通用模板/SpringBoot整合
登录功能的思路 前端会传入两个参数:用户名和密码 在用户表中查询用户名,并校对相应的密码(涉及查询操作) SQL语句 select * from emp where username jingyong and password 123456; 如果有则成功,没有则登录失败.不可能为多个,因为添加了unique唯一约束,最终只会有一条 …...
The 2023 ICPC Asia Regionals Online Contest (1)(A D I J K L)
The 2023 ICPC Asia Regionals Online Contest (1)(A D I J K L) PTA | 程序设计类实验辅助教学平台 A Qualifiers Ranking Rules(模拟) 考虑先对第一场和第二场分别去重(取最好) , 归并排序后再次去重即可。 #include<bits/stdc.h> using namespace std;…...
C++ PrimerPlus 复习 第七章 函数——C++的编程模块(上)
第一章 命令编译链接文件 make文件 第二章 进入c 第三章 处理数据 第四章 复合类型 (上) 第四章 复合类型 (下) 第五章 循环和关系表达式 第六章 分支语句和逻辑运算符 第七章 函数——C的编程模块(上ÿ…...
2.求循环小数
题目 对于任意的真分数 N/M ( 0 < N < M ),均可以求出对应的小数。如果采用链表表示各个小数,对于循环节采用循环链表表示,则所有分数均可以表示为如下链表形式。 输入: N M 输出: 转换…...
zabbix监控告警邮箱提醒,钉钉提醒
一、注册网易邮箱及其配置邮箱 1、开启POP3/SMTP/IMAP 二、service端配置邮件服务 1.安装 mailx dos2unix yum install -y mailx dos2unix mailx:邮件服务 mos2unix:用于转换文本文件格式的实用工具 查看mailx版本 2.配置mailx配置文件 编辑…...
典型数据结构-栈/队列/链表、哈希查找、二叉树(BT)、线索二叉树、二叉排序树(BST树)、平衡二叉树(AVL树)、红黑树(RB树)
目录 典型数据结构列举 栈/队列/链表 树 二叉树 线索二叉树 二叉排序树 平衡二叉树(AVL树) 红黑树 其它树种和应用介绍 典型数据结构列举 栈/队列/链表 描述略。 一些基本的简单实现参考/数据结构简单实现/文件夹里面。 线性表详解ÿ…...
pyarmor 加密许可证的使用
一 pyarmor 许可证的用处 文档:5. 许可模式和许可证 — Pyarmor 8.3.6 文档 试用版本有如下的限制: 加密功能对脚本大小有限制,不能加密超过限制的大脚本。 混淆字符串功能在试用版中无法使用。 RFT 加密模式,BCC 加密模式在试…...
网络路径监控分析
不间断的连接应该是任何企业的首要任务。然而,确保网络中的源和目标之间持续、不间断的联系一直是网络通信中一个劳动密集型的过程。了解网络路径中的障碍、识别它们并迅速解决它们以维护健康、不间断的网络至关重要。 为什么要监控网络路径 维护网络运行状况是任…...
vue双向数据绑定是如何实现的?
Vue中的双向数据绑定主要是通过数据劫持和发布订阅模式来实现的。 数据劫持: Vue通过使用Object.defineProperty()方法来对data对象中的属性进行劫持,从而实现对数据的双向绑定。具体实现方式为: (1)在Vue实例化时&a…...
轴承 网站建设 企炬/seo顾问张智伟
LDAP介绍LDAP概述LDAP是轻量目录访问协议,(LDAP, Lightweight Directory Access Protocol)LDAP是用于访问目录服务(特别是基于X.500的目录服务),LDAP在TCP/IP或其他面向连接的传输服务上运行。LDAP是IETF标准的跟踪协议。 LDAP是目录非关系型的&#…...
国家 住房城乡建设信用 网站/微信营销号
ylbtech-开发框架:目录1.返回顶部 1、https://adminlte.io2、2.返回顶部3.返回顶部4.返回顶部5.返回顶部 6.返回顶部作者:ylbtech出处:http://ylbtech.cnblogs.com/本文版权归作者和博客园共有,欢迎转载,但未经作者同意…...
专门做二手手机的网站/百度搜索网页
python如何识别图片中的文字,这里给个案例并附上详细步骤:模块包的安装:1、安装PIL:pip install Pillow2、安装pytesser3:pip install pytesser33、安装pytesseract:pip install pytesseract4、安装autopy3…...
网站建设开发ppt模板/百度百科词条入口
Python 初学者的经验总结 python须知 1.区分大小写(sql语言不区分大小写),类第一个字母大写,函数方法第一个字母小写。 2.对空格很依赖(其他编程语言依赖大括号) 3.Errors出错不可怕,只是计…...
网络营销网站的建设与策划/济南优化网络营销
Django处理一个请求 项目启动后根据 settings ROOT_URLCONF 决定项目根URLconf urlpatterns是django.conf.urls.url()实例的一个Python列表 Django依次匹配每个URL模式,匹配成功后就停止 Django匹配成功,调用相应视图函数(或一个基于类的视图)&#…...
seo 网站关键词优化/诊断网站seo现状的方法
无缘参加去年在广州的UCD年会,这个周末还是想方法去杭州参加了UCD2010年会,收益良多,如果真要细细写下来,恐怕足够写成一本厚厚的垃圾书,只好视自己的心情想到什么就写什么吧。 虽然一直对网络营销抱有浓厚的兴趣&a…...