MySQL的批量更新和批量插入优化

如果需要批量插入和批量更新操作就需要进行sql 的优化,否则近30万条数据的插入或更新就会耗费几分钟甚至更多的时间, 此文仅批量插入和批量更新的几种优化。

  • 批量插入篇(使用多条insert语句、使用union all创建临时表、使用多个values);
  • 批量更新篇(使用多条update语句、使用union all创建临时表创建临时表、使用replace into、使用insert ... on duplicate key ... update...)。

如果有需要的同僚可根据下列内容使用jdbcTemplate和Java反射技术将其封装。特别提示:做批量操作时,请限制每次1000-2000条数据,以避免GC和OOM。后期也会贴出相关代码,欢迎指正优化或提供其它更好的方法。

批量插入篇

1. 多条insert语句(快)

实测:50*6500行数据耗时8-12秒,如果不是手动提交事务,耗时约70-180秒

类型:insert into table_name(id,name,title) values(?, ?, ?);

常用的插入操作就是批量执行1条insert类型的SQL语句,这样的语句在执行大量的插入数据时, 其效率低下就暴露出来了。
特别注意:jdbc.url需要加上:allowMultiQueries=true

jdbc.url = jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&allowMultiQueries=true

(1)sql 语句

start transaction;
insert into table_name(id, name, title) values(1, '张三', '如何抵挡美食的诱惑?');
insert into table_name(id, name, title) values(2, '李四', '批判张三的《如何抵挡美食的诱惑?》');
insert into table_name(id, name, title) values(3, '王五', '会看鬼子进村的那些不堪入目的事儿');
insert into table_name(id, name, title) values(4, '赵柳', 'Java该怎样高效率学习');
commit;

(2)mapper 文件的 sql

<insert id="batchSave"  parameterType="java.util.List">start transaction;<foreach collection="list" index="index" item="item">insert into table_name(id, name, title) values(#{item.id}, #{item.name}, #{item.title});</foreach>commit;
</insert>

2. 多个values语句(快)

实测:50*6500行数据耗时6至10秒(与服务器的有关)

类型:insert into table_name(id, name, title) values(?, ?, ?), ..., (?, ?, ?);

(1)sql 语句

insert into table_name(id, name, title)
values(1, '张三', '如何抵挡美食的诱惑?'),(2, '李四', '批判张三的《如何抵挡美食的诱惑?》'),(3, '王五', '会看鬼子进村的那些不堪入目的事儿'),(4, '赵柳', 'Java该怎样高效率学习');

(2)mapper 文件的 sql

<insert id="batchSave"  parameterType="java.util.List">insert into table_name(id, name, title) values<foreach collection="list" index="index" item="item" separator=", ">(#{item.id}, #{item.name}, #{item.title})</foreach>
</insert>

3. 使用union all 创建临时表(快)

实测:50*6500行数据耗时6至10秒(与服务器的有关)

类型:insert into table_name(id,name,title) select ?, ?, ? union all select ?, ?, ? union all ...

union all 在这里select ?, ?, ? union all select ?, ?, ? union all ...是创建临时表的原理,先创建整张临时表到内存中,然后将整张临时表导入数据库,连接关闭时即销毁临时表,其他的不多说,可自行了解。

(1)sql 语句

insert into  table_name(id, name, title)
select 1, '张三', '如何抵挡美食的诱惑?'
union all
select 2, '李四', '批判张三的《如何抵挡美食的诱惑?》'
union all
select 3, '王五', '会看鬼子进村的那些不堪入目的事儿'
union all
select 4, '赵柳', 'Java该怎样高效率学习';
a. 创建临时表方式1 - 使用 temporary + union all

简单列举三种创建临时表的方式, 这里熟悉了temporaryselect ?, ? ,? union all select ?, ?, ? 和 、insert into ... values(?, ?, ?), (?, ?, ?), (?, ?, ?)...之后,都可以组合创建临时表, 效率几乎差不多。个人更加偏向第二种,因为简单方便。

create temporary table tmp(id int(4) primary key,name varchar(50),title varchar(50));
SELECT id, name, title FROM tmp
union all
select 1, '张三', '如何抵挡美食的诱惑?'
union all
select 2, '李四', '批判张三的《如何抵挡美食的诱惑?》'
union all
select 3, '王五', '会看鬼子进村的那些不堪入目的事儿'
union all
select 4, '赵柳', 'Java该怎样高效率学习';

b. 创建临时表方式2 - 使用 select + union all
select id, name, title from table_name where id = -1
union all
select 1, '张三', '如何抵挡美食的诱惑?'
union all
select 2, '李四', '批判张三的《如何抵挡美食的诱惑?》'
union all
select 3, '王五', '会看鬼子进村的那些不堪入目的事儿'
union all
select 4, '赵柳', 'Java该怎样高效率学习';

c. 创建临时表方式3 - 使用 temporary + 多个insert values
create temporary table tmp(id int(4) primary key,name varchar(50),title varchar(50));
insert into tmp(id, name, title)
values(1, '张三', '如何抵挡美食的诱惑?'),(2, '李四', '批判张三的《如何抵挡美食的诱惑?》'),(3, '王五', '会看鬼子进村的那些不堪入目的事儿'),(4, '赵柳', 'Java该怎样高效率学习');

(2)mapper 文件的 sql

<insert id="batchSave"  parameterType="java.util.List">insert into table_name(id, name, title) <foreach collection="list" index="index" item="item" separator=" union all ">select #{item.id}, #{item.name}, #{item.title}</foreach>
</insert>

批量更新篇

1. 多条update语句批量更新(快)

实测:50*6500行数据耗时26-30秒,如果不是手动提交事务,耗时约70-180秒

类型:update table_name set name = ?, title = ? where id = ?;

由于批量更新存在条件判断,所以整体上时效上没有批量插入那么高(下面是手动提交事务的代码)。
特别注意:jdbc.url需要加上:allowMultiQueries=true

jdbc.url = jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC&allowMultiQueries=true

(1)sql 语句

start transaction;
update table_name set name = '张三', title = 'springboot如何入门' where id = 1;
update table_name set name = '李四', title = 'JVM到底是怎样运行的' where id = 2;
update table_name set name = '王五', title = '并发编程你需要注意什么' where id = 3;
update table_name set name = '赵柳', title = '别让一时的贪成为你不努力的理由' where id = 4;
commit;

(2)mapper 文件的 sql

<update id="batchUpdate"  parameterType="java.util.List">start transaction;<foreach collection="list" index="index" item="item">update table_name set name = #{item.id}, title = #{item.title} where id = #{item.id};</foreach>commit;
</update >

2. 创建临时表批量更新(快)

实测:50*6500行数据耗时26至28秒

(1)批量更新(使用 temporary + select … union all … select …创建临时表)

类型:create temporary table 临时表;select id, name, title FROM 临时表 union all select ... union all ... select ...
(A)sql 语句

这里也可以使用 union all 加上 temporary 的方式创建临时表, 详情请看批量插入篇的创建临时表的两种方式

create temporary table tmp(id int(4) primary key,name varchar(50),title varchar(50));
select id, name, title from tmp
union all
select 1, '张三', '如何抵挡美食的诱惑?'
union all
select 2, '李四', '批判张三的《如何抵挡美食的诱惑?》'
union all
select 3, '王五', '会看鬼子进村的那些不堪入目的事儿'
union all
select 4, '赵柳', 'Java该怎样高效率学习';
update table_name, tmp set table_name.name=tmp.name, table_name.title= tmp.title where table_name.id = tmp.id;
(B)mapper 文件的 sql
<update id="batchUpdate"  parameterType="java.util.List">create temporary table tmp(id int(4) primary key,name varchar(50),title varchar(50));update table_name, (SELECT id, name, title FROM tmp union all <foreach collection="list" index="index" item="item" separator=" union all ">select #{item.id}, #{item.name}, #{item.title}</foreach>) as tmpset table_name.name=tmp.name, table_name.title= tmp.title where table_name.id = tmp.id;
</insert>

(2)批量更新(使用 temporary + insert into values(…), (…)… 创建临时表)

类型:create temporary table 临时表;insert into values(...), (...)...;update ... set ... where ...;
(A)sql 语句

这里也可以使用 union all 加上 temporary 的方式创建临时表, 详情请看批量插入篇的创建临时表的两种方式

create temporary table tmp(id int(4) primary key,name varchar(50),title varchar(50));
insert into tmp(id, name, title)
values(1, '张三', '如何抵挡美食的诱惑?'),(2, '李四', '批判张三的《如何抵挡美食的诱惑?》'),(3, '王五', '会看鬼子进村的那些不堪入目的事儿'),(4, '赵柳', 'Java该怎样高效率学习') ;
update table_name, tmp set table_name.name=tmp.name, table_name.title= tmp.title where table_name.id = tmp.id;
(B)mapper 文件的 sql
<update id="batchUpdate"  parameterType="java.util.List">create temporary table tmp(id int(4) primary key,name varchar(50),title varchar(50));insert into tmp(id, name, title) values<foreach collection="list" index="index" item="item" separator=",">(#{item.id}, #{item.name}, #{item.title})</foreach>;update table_name, tmp set table_name.name=tmp.name, table_name.title= tmp.title where table_name.id = tmp.id;
</insert>

(3)批量更新(使用 select … union all… 创建临时表)

类型:update 表名, (select ... union all ...) as tmp set ... where ...

注意: id=-1为数据库一个不存在的主键id

(A)sql 语句
update table_name, (select id, name, title from table_name where id = -1 union all
select 1, '张三', '如何抵挡美食的诱惑?' union all
select 2, '李四', '批判张三的《如何抵挡美食的诱惑?》' union all
select 3, '王五', '会看鬼子进村的那些不堪入目的事儿' union all
select 4, '赵柳', 'Java该怎样高效率学习') as tmp
set table_name.name=tmp.name, table_name.title= tmp.title where table_name.id = tmp.id;
(B)mapper 文件的 sql
<update id="batchUpdate"  parameterType="java.util.List">update table_name, (select id, name, title from table_name where id = -1 union all<foreach collection="list" index="index" item="item" separator=" union all ">select #{item.id}, #{item.name}, #{item.title}</foreach>) as tmpset table_name.name=tmp.name, table_name.title= tmp.title where table_name.id = tmp.id;
</insert>

3. replace into …批量更新(快)

实测:50*6500行数据耗时26至28秒

类型:replace into ... values (...),(...),...

(1)sql 语句

replace into table_name(id, name, title)
values(1, '张三', '如何抵挡美食的诱惑?'),(2, '李四', '批判张三的《如何抵挡美食的诱惑?》'),(3, '王五', '会看鬼子进村的那些不堪入目的事儿'),(4, '赵柳', 'Java该怎样高效率学习') ;

(2)mapper 文件的 sql

<update id="batchUpdate"  parameterType="java.util.List">replace into table_name(id, name, title) values<foreach collection="list" index="index" item="item" separator=",">(#{item.id}, #{item.name}, #{item.title})</foreach></update>

4. insert into … on duplicate key … update …批量更新(快)

实测:50*6500行数据批量更新耗时27-29秒, 批量插入耗时9-12秒

类型:insert into ... values (...),(...),...on duplicate key ... update ...

这句类型的SQL在遇到 duplicate key 时执行更新操作, 否则执行插入操作(时效略微慢一点)

(1)sql 语句

insert into table_name(id, name, title)
values(1, '张三', '如何抵挡美食的诱惑?'),(2, '李四', '批判张三的《如何抵挡美食的诱惑?》'),(3, '王五', '会看鬼子进村的那些不堪入目的事儿'),(4, '赵柳', 'Java该怎样高效率学习')
on duplicate key update name=values(name), title=values(title);

(2)mapper 文件的 sql

<update id="batchUpdate"  parameterType="java.util.List">replace into table_name(id, name, title) values<foreach collection="list" index="index" item="item" separator=",">(#{item.id}, #{item.name}, #{item.title})</foreach>on duplicate key update id= values(id);</update>

MySQL的批量更新和批量新增优化相关推荐

  1. mysql 批量update sql_批量更新sql |批量update sql

    zencart批量更新后台邮箱地址sql zencart批量更新后台邮箱地址sql UPDATE `configuration` SET `configuration_value` = '新邮箱地址' ...

  2. batchupdate写法_批量更新sql_批量update_sql(Batch update sql_ batch update_sql).doc

    批量更新sql_批量update_sql(Batch update sql_ batch update_sql) 批量更新sql_批量update_sql(Batch update sql_ batc ...

  3. yii 全选 php,Yii2.0实现的批量更新及批量插入功能示例

    本文实例讲述了Yii2.0实现的批量更新及批量插入功能.分享给大家供大家参考,具体如下: 批量更新 方法1 /** * 批量更新循环周期 * @param array $condition * $co ...

  4. ef oracle 批量更新慢_详解Oracle中多表关联批量插入、批量更新与批量删除

    概述 今天主要介绍一下Oracle数据库中多表关联批量插入.多表关联批量更新和多表关联批量删除.下面用实验来理解下~ 一.创建必须的表和序列语句 --创建部门表 dept:CREATE TABLE d ...

  5. mybatis mysql 批量更新_mysql批量update更新,mybatis中批量更新操作

    在日常开发中,有时候会遇到批量更新操作,这时候最普通的写法就是循环遍历,然后一条一条地进行update操作.但是不管是在服务端进行遍历,还是在sql代码中进行遍历,都很耗费资源,而且性能比较差,容易造 ...

  6. MySql数据库Update批量更新与批量更新多条记录的不同值实现方法

    批量更新 mysql更新语句很简单,更新一条数据的某个字段,一般这样写: UPDATE mytable SET myfield = 'value' WHERE other_field = 'other ...

  7. mysql批量更新,批量插入之replace语句/insert into... on duplicate key update语句

    mysql批量更新/插入数据有以下方法,使用这些方法批量插入数据/更新数据的时候就不用在代码层次增加判断数据是否已存在的逻辑了. 1:replace语句 2: insert into... on du ...

  8. mysql jdbc驱动 批量更新_jdbc批量插入,删除,更新

    批量处理:一次向数据库发送多个SQL语句时,可以减少通信开销,从而提高性能. 不确定JDBC驱动程序是否支持此功能.应该使用DatabaseMetaData.supportsBatchUpdates( ...

  9. mysql 批量更新数据 备份_mysql 批量更新与批量更新多条记录的不同值实现方法...

    批量更新 mysql更新语句很简单,更新一条数据的某个字段,一般这样写: UPDATE mytable SET myfield = 'value' WHERE other_field = 'other ...

最新文章

  1. 【腾讯面试题】熊出没
  2. hadoop集群环境搭建准备工作
  3. 《HTTP权威指南》– 5.Web服务器
  4. 汉高澳大利亚sinox接口捆绑经典winxp,全面支持unicode跨语言处理
  5. UVA 413|LA 5388|POJ 1492|ZOJ 1338 Up and Down Sequences
  6. xp关无线配置服务器,xp系统怎么关闭无线功能
  7. 进程间通信 - 邮槽实现
  8. AJPFX讲解Java 性能优化[4]:关于 finalize 函数
  9. elk系列1之入门安装与基本操作
  10. tomcat lifecyclelistener_大公司程序员带你死磕Tomcat系列(五)——容器
  11. 【SQL】SQL语法树
  12. linux 设置端口常用命令
  13. trump可音译为“专普”
  14. 计算机公式求所占百分比,如何使用Excel函数计算所占的比例
  15. 建筑竞赛获奖项目解析国外教程
  16. Python 实现一个自动下载小说的简易爬虫
  17. Ubuntu 设置桥接网络
  18. STM8电源模式管理及功耗控制
  19. 冒烟测试(smoke test)、可用性测试(sanity test)和回归测试(regression test)
  20. 51单片机内存动态分配

热门文章

  1. ch352l串口卡驱动
  2. zzuli:1115数组最小值
  3. 手机软件系统测试用例设计大全
  4. 项目场景:对接支付宝支付,沙箱环境提示:支付存在钓鱼风险!防钓鱼网站的方法
  5. AOSP编译速通指南
  6. 求凸多边形最长的面积平分线。
  7. 进销存管理系统是什么?进销存管理系统优点?
  8. fio使用good blog
  9. Cyanine7 NH2|分子式C43H60Cl2N4O|分子量719.87|保存条件
  10. 小米手机通过电脑上网