Mysql 批量插入大量数据的两种方案以及优缺点(分别是 5W 条数据和 10W 条数据)
时间:2023-03-04 02:00:00
Mysql 批量插入(5W 条数据和 10W 条数据)
1.批量插入思路
一般有两种不同的想法:
1、for 批量插入循环
2、生成一条 SQL 语句,比如 insert into user(id,username) values(1,“zs),ls”)…
2.两种思维的优缺点
a、for循环的优缺点
如果是 for 优点是:
- PreparedStatement 具有预编译功能。
劣势:
- 要插入 10W 次,需要 10W 次网络 IO。
b、SQL 句子的优缺点
如果是单条 SQL 句子的优点是:
- 一条 SQL 只需要一次网络 IO。
劣势:
- 单条 SQL 过大,需要对数据分片。比如 10W 条数据分为两条,包括 5W 数据的 SQL 语句。
- 单条 SQL 语句过大,MySQL 降低分析速度。
- 不能充分发挥 PreparedStatement 预编译功能。
3.开始测试(这里测试) 5W 条数据)
首先在数据库中创建一个表。这个可以自己创建。
本来打算测试 10W 插入条数据。但是因为单条 SQL 句子太大,会报错,需要分片。虽然分片不难,但与主题无关,所以在这里使用 5W 测试条数据。效果是一样的。结论是一样的。
a、前期准备
这里用的是 SpringBoot 项目。
这里展示测试中使用的依赖:
pom.xml 加这样一段:
数据库:
然后是 mapper:
实体类自己看情况写;
然后是 service:
为有效地看到效果,这里先演示一下错误的写作方法:
b、开始测试(最原始的 for 循环)
测试代码:
结果:
其实这里演示的很原始 for 循环使用循环 jdbc 内部提供的批处理。
b、第二次测试(使用 jdbc 的批处理)
若要使用 jdbc 提供的批处理功能,那么有个强制性的要求就是 sql 句子最后不能有分号。 看下图:
但这还不够,如果只是这样,还是不需要批处理。还需要配置文件数据库 url 在那一块的最后需要添加一个参数, 如果不添加此参数,即使代码使用批处理,jdbc 这个参数也会被忽略,看下图:
不够,不能用 mapper,因为这个东西没有使用批处理的功能,这是很常见的 mapper。首先获取数据库链接,然后执行插入,插入需要打开事务,然后提交事务,然后打开事务插入;这样执行 5W 第二,效率不慢吗?
因此,有必要获得批处理功能 mapper;修改 service 代码:
到此结束。
然后清空数据,然后执行:
最终测试效果:
可以看出,很明显,效率要快得多。之所以能这么快,不仅是因为开启了批处理功能,还因为博主的性能太好,所以会很快。
c、第三次测试(单条 SQL)
mapper :
server:
测试代码:
最终效果:
可见明显是比批处理。 for 循环慢的。
4、测试 10W 条数据
这里直接得出结论
a、批处理 for 循环
b、单条 SQL 语句
请注意,这里有可能报告这个错误:
单条 SQL 语句过大。
这里有两决方案:一是分片,分片变小 SL 语句去执行插入,但是这本来效率就比上面的慢, 还要分片,那就更慢了。
二是去 C盘下的 mysql 的配置文件 my.ini(这里自行百度路径)里面的 max_allowed_packet 。如果没有,可以自行添加在 [ mysqld ] 下面。去修改里面的默认大小,默认缓存是 1M,这里为了方便测试改成了 16M(16 * 1024 * 1024)。
然后最终结果:
5、最终结论
最终结论就是:
批处理的 for 循环比 单条 SQL 语句更快。
如果是慢的,要检查数据库 url 那里有没有参数,或者有没有打错。