MySQL数据库导入100万数据不同方式的性能差异

本文将介绍MySQL数据库导入100万数据的三种方式性能比较。

三种方式分别为:

(1)逐条INSERT

(2)批量INSERT提交

(3)通过mysql自带的load data命令

应用场景:假设需要向100万个号码发送短信,收到了100万个号码txt文件,现需要将号码导入到数据库,通过短信系统发送短信。向数据库导入数据的场景还有很多,比如在新老系统切换的时候,需要将老系统的数据迁移导入到新系统,这些都可能涉及到大量数据导入的问题。

首先,我们先准备数据库表、100万个号码、生成insert语句的java代码、批量向数据库提交insert语句的java代码。

(1)数据库表如下:

(2) 生成100万个号码

package com.fd.demo.common;import org.springframework.stereotype.Component;import java.io.*;/*** @Author: thinkpad* @Date: 2023-12-30 9:23*/
@Component
public class TelephoneGenerate {/*** 生成号码个数* @param count*/public void generate(int count) throws Exception{String telephoneBase = "13900000000";if(count > 100000000){throw new Exception("号码生成个数最大不能超过1亿");}String fileName = "telephoneGenerate.txt";File file = new File(fileName);if(!file.exists()){file.createNewFile();}// demo代码 不考虑异常情况FileOutputStream fileOutputStream = new FileOutputStream(file);OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);for(int i = 0; i < count; i++){String str = String.valueOf(i);String telephone = telephoneBase.substring(0, 11-str.length()) + str;bufferedWriter.write(telephone);bufferedWriter.write("\n");}bufferedWriter.flush();bufferedWriter.close();outputStreamWriter.close();fileOutputStream.close();}public static void main(String[] args) throws Exception {TelephoneGenerate telephoneGenerate = new TelephoneGenerate();long beginTime = System.currentTimeMillis();telephoneGenerate .generate(1000000);long endTime = System.currentTimeMillis();System.out.println("cost time: " + (endTime - beginTime) + "ms");}
}

(3) 生成100万条insert语句

package com.fd.demo.common;import org.springframework.stereotype.Component;import java.io.*;
import java.util.Objects;/*** @Author: thinkpad* @Date: 2023-12-30 9:22*/
@Component
public class MySQLInsertGenerate {/*** 生成insert语句*/public void generateInsertSQL() throws Exception{String fileName = "telephoneGenerate.txt";File file = new File(fileName);// demo代码 不考虑异常情况FileInputStream fileInputStream = new FileInputStream(file);InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String sqlFileName = "telephoneInsertSQL.txt";File sqlFile = new File(sqlFileName);FileOutputStream fileOutputStream = new FileOutputStream(sqlFile);OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);String telephone = bufferedReader.readLine();while(!Objects.isNull(telephone) && !"".equals(telephone)){TelephoneRecvListVO telephoneRecvListVO = new TelephoneRecvListVO();telephoneRecvListVO.setId(IdWorker.nextId()); //雪花算法生成idtelephoneRecvListVO.setAppId(2);telephoneRecvListVO.setAppName("demo");telephoneRecvListVO.setTemplateId(2);telephoneRecvListVO.setTemplateContent("测试短信内容发送");telephoneRecvListVO.setTelephoneList(telephone); // 如果有多个号码,以短号隔开telephoneRecvListVO.setCreateDate("20231230");telephoneRecvListVO.setCreateTime("170000");telephoneRecvListVO.setStatus("9"); // 9初始状态 0已发送 1发送失败 2发送中String insertSql = generate(telephoneRecvListVO);bufferedWriter.write(insertSql);bufferedWriter.write("\n");telephone = bufferedReader.readLine();}bufferedWriter.flush();bufferedWriter.close();outputStreamWriter.close();fileOutputStream.close();inputStreamReader.close();fileInputStream.close();}// 可以使用反射进行组装private String generate(TelephoneRecvListVO telephoneRecvListVO){StringBuilder sb = new StringBuilder();sb.append("insert into recv_list(ID, APP_ID, APP_NAME, TEMPLATE_ID, TEMPLATE_CONTENT, TELEPHONE_LIST, CREATE_DATE, CREATE_TIME, STATUS) values(");sb.append(telephoneRecvListVO.getId());sb.append(",");sb.append(telephoneRecvListVO.getAppId());sb.append(",");sb.append("'" + telephoneRecvListVO.getAppName() + "'");sb.append(",");sb.append(telephoneRecvListVO.getTemplateId());sb.append(",");sb.append("'" + telephoneRecvListVO.getTemplateContent() + "'" );sb.append(",");sb.append("'" + telephoneRecvListVO.getTelephoneList() + "'" );sb.append(",");sb.append("'" + telephoneRecvListVO.getCreateDate() + "'");sb.append(",");sb.append("'" + telephoneRecvListVO.getCreateTime() + "'");sb.append(",");sb.append("'" + telephoneRecvListVO.getStatus() + "'");sb.append(");");return sb.toString();}public static void main(String[] args) throws Exception {MySQLInsertGenerate generate = new MySQLInsertGenerate();long beginTime = System.currentTimeMillis();generate.generateInsertSQL();long endTime = System.currentTimeMillis();System.out.println("cost time: " + (endTime - beginTime) + " ms");}
}

(4)单笔向recv_list插入数据

package com.fd.demo.mysqlinsert;import java.io.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Objects;/*** @Author: thinkpad* @Date: 2023-12-30 19:07*/
public class SingleInsert {public void singleInsert() throws Exception {File file = new File("telephoneInsertSQL.txt");FileInputStream fileInputStream = new FileInputStream(file);InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);try{Connection conn = MySqlJDBC.getConnection();String sql = bufferedReader.readLine();long currentIndex = 1;while(!Objects.isNull(sql) && !"".equals(sql)){if(currentIndex%10000 == 0){System.out.println("Current Index = " + currentIndex);}PreparedStatement ps = conn.prepareStatement(sql);ps.execute();sql = bufferedReader.readLine();currentIndex++;}}catch (Exception e){e.printStackTrace();}bufferedReader.close();inputStreamReader.close();fileInputStream.close();}public static void main(String[] args) throws Exception {SingleInsert singleInsert = new SingleInsert();long beginTime = System.currentTimeMillis();singleInsert.singleInsert();long endTime = System.currentTimeMillis();System.out.println("cost time: " + (endTime - beginTime) + " ms");}
}

单笔总共花费时间:将近31小时

(5)批量向recv_list插入数据(每10000笔提交一次事务)

package com.fd.demo.mysqlinsert;import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.Statement;
import java.util.Objects;/*** @Author: thinkpad* @Date: 2023-12-30 19:23*/
public class BatchInsert {public void batchInsert() throws Exception{File file = new File("telephoneInsertSQL.txt");FileInputStream fileInputStream = new FileInputStream(file);InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);BufferedReader bufferedReader = new BufferedReader(inputStreamReader);try{Connection conn = MySqlJDBC.getConnection();Statement statement = conn.createStatement();conn.setAutoCommit(false); // 批量插入主要是不自动提交事务,String sql = bufferedReader.readLine();long currentIndex = 1;while(!Objects.isNull(sql) && !"".equals(sql)){statement.executeUpdate(sql);if(currentIndex % 10000 == 0){System.out.println("currentIndex = " + currentIndex);conn.commit();}sql = bufferedReader.readLine();currentIndex++;}}catch (Exception e){e.printStackTrace();}bufferedReader.close();inputStreamReader.close();fileInputStream.close();}public static void main(String[] args) throws Exception {BatchInsert batchInsert = new BatchInsert();long beginTime = System.currentTimeMillis();batchInsert.batchInsert();long endTime = System.currentTimeMillis();System.out.println("cost time: " + (endTime - beginTime) + " ms");}
}

批量插入数据,仅花费了4分钟,完全秒杀单笔插入的效率。

(6)使用mysql的load data命令

load data infile 'G:/idea_workspace/MySQLPerformance/telephoneImportSQL.txt' 
into table recv_list fields terminated by ',' enclosed by '"' 
lines terminated by '\n';

如果在执行的过程中发生以下错误:

ERROR 1261 (01000):Row 1 doesn't contain data for all colums

这是因为sql_mode 被设为了 strict 模式, 要想继续导入需要把“strict_trans_tables” 从 sql_mode 中去掉.

查看 MySQL 当前连接的 sql_mode

mysql> show variables like 'sql_mode';

临时修改sql_mode

mysql> set sql_mode='';

 使用load data命令花了2分26秒的时间,比批量导入快了近一倍。

通过上述比较,可以看出load data命令的性能最佳,其次是批量导入,最差的是单笔插入。

上述所有代码工程见 https://download.csdn.net/download/flyingcloude/88681843?spm=1001.2014.3001.5503

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL】事务Transaction

1. 事务的概念 事务是什么 在业务逻辑中使用sql&#xff0c;面对一些较复杂的场景&#xff0c;是需要多个sql语句组合起来实现的。如&#xff1a;银行的转账业务&#xff0c;若客户A要转账100元给客户B&#xff0c;就要两条sql&#xff1a;A余额减100&#xff0c;B余额加100&a…

手拉手Springboot获取yml配置文件信息

环境介绍 技术栈 springboot3 软件 版本 mysql 8 IDEA IntelliJ IDEA 2022.2.1 JDK 17 Spring Boot 3.1.7 配置文件说明&#xff1a;启动配置文件优先级&#xff1a;properties高于yml 配置文件application.yml yml是 JSON 的超集&#xff0c;简洁而强大&#xf…

[Angular] 笔记 24:ngContainer vs. ngTemplate vs. ngContent

请说明 Angular 中 ngContainer&#xff0c; ngTemplate 和 ngContent 这三者之间的区别。 chatgpt 回答&#xff1a; 这三个在 Angular 中的概念是关于处理和组织视图的。 1. ngContainer&#xff1a; ngContainer 是一个虚拟的 HTML 容器&#xff0c;它本身不会在最终渲染…

YOLOv8改进 | 2023注意力篇 | EMAttention注意力机制(附多个可添加位置)

一、本文介绍 本文给大家带来的改进机制是EMAttention注意力机制&#xff0c;它的核心思想是&#xff0c;重塑部分通道到批次维度&#xff0c;并将通道维度分组为多个子特征&#xff0c;以保留每个通道的信息并减少计算开销。EMA模块通过编码全局信息来重新校准每个并行分支中…

Axure骚操作:【制作可暂停与不可暂停进度加载条】

目录 一、不可暂停进度条 1.1 前期准备 1.2 效果假想 1.3 适用场景 1.4 实现步骤 &#xff08;1&#xff09;除按钮外的元件设置隐藏 &#xff08;2&#xff09;给按钮添加交互 &#xff08;3&#xff09;给变量值文本标签添加交互 &#xff08;4&#xff09;给进度条矩…

DrGraph原理示教 - OpenCV 4 功能 - 颜色空间

前言 前段时间&#xff0c;甲方提出明确需求&#xff0c;让把软件国产化。稍微研究了一下&#xff0c;那就转QT开发&#xff0c;顺便把以前的功能代码重写一遍。 至于在Ubuntu下折腾QT、OpenCV安装事宜&#xff0c;网上文章很多&#xff0c;照猫画虎即可。 这个过程&#xff0…

『番外篇七』SwiftUI 获取视图全局位置在 NavigationStack 中失效的解决方法

概览 在 番外篇六』SwiftUI 取得任意视图全局位置的三种方法 这篇博文里,我们详细讨论了在 SwiftUI 中获取任意视图全局坐标的几种方法。 不过,我们也从中提到了某些方法无法适用于 NavigationStack 视图,本篇博文由此应运而生。 在本篇博文种,您将学到如下内容: 概览1.…

Redis:原理速成+项目实战——Redis的Java客户端

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;Redis&#xff1a;原理速成项目实战——Redis常见命令&#xff08;数据结构、常见命令总结&#xff09; &#x1f4da;订阅专栏&…

Git:远程仓库的使用

查看当前的远程库 要查看当前配置有哪些远程仓库&#xff0c;可以用git remote 命令&#xff0c;它会列出每个远程库的简短名字。在克隆完某个项目后&#xff0c;至少可以看到一个名为origin 的远程库&#xff0c;Git 默认使用这个名字来标识你所克隆的原始仓库&#xff1a; 也…

ubuntu下编译obs-studio遇到的问题记录

参考的是这篇文档&#xff1a;Build Instructions For Linux obsproject/obs-studio Wiki GitHub 在安装OBS dependencies时&#xff0c; sudo apt install libavcodec-dev libavdevice-dev libavfilter-dev libavformat-dev libavutil-dev libswresample-dev libswscale-d…

webpack打包批量替换路径(string-replace-webpack-plugin插件)

string-replace-webpack-plugin 是一个用于在 webpack 打包后的文件中替换字符串的插件。它可以用于将特定字符串替换为其他字符串&#xff0c;例如将敏感信息从源代码中移除或对特定文本进行本地化处理。比如文件的html、css、js中的路径地址想批量更改一下 http://localhost:…

QT上位机开发(乘法计算小软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面一篇文章&#xff0c;我们学习了怎么创建qt的第一个工程&#xff0c;怎么用designer给qt修改界面。虽然我们到目前为止&#xff0c;还没有编写…