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()); //雪花算法生成id
            telephoneRecvListVO.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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML 基础

文章目录 01-标签语法标签结构 03-HTML骨架04-标签的关系05-注释06-标题标签07-段落标签08-换行和水平线09-文本格式化标签10-图像标签图像属性 11-路径相对路径绝对路径 12-超链接标签13-音频14-视频 01-标签语法 HTML 超文本标记语言——HyperText Markup Language。 超文本…

Plantuml之YAML效果图语法介绍(二十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Apollo自动驾驶系统:实现城市可持续交通的迈向

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 ChatGPT体验地址 文章目录 前言引言&#xff1a;1. 什么是微服务架构&#xff1f;2. 微服务架构的组成要素3. 微服务架构的挑战和解决方案4. 微服务架构的可扩展性和弹性 第二部分&#x…

【Simulink系列】——用扫地机器人实例快速引入

目录 一、Simulink基本认知 1、模块图建模 2、仿真基本流程 3、调试技巧 二、基于模型的simulink设计实例&#xff08;两轮扫地机器人&#xff09; 1、系统定义与布局 确定建模目的 确定系统组件和接口 确定系统布局 2、建模并验证系统 对组件建模 ①物理组件建模 …

短说社区运营的使用工具分享(一)

本文是一篇针对短说社区运营的使用工具分享帖&#xff0c;是小编结合日常使用&#xff0c;总结的一些可以帮助网站管理员和运营人员进行日常操作和管理的工具。 1. 想天工作台之运营面板 想天工作台可以将桌面划分不同的类型来辅助办公&#xff0c;我分享下我当前的桌面情况&…

程序员必备IDEA插件,什么是是IDE?

IDEA是一款功能强大的集成开发环境&#xff08;IDE&#xff09;插件&#xff0c;它可以帮助开发人员更加高效地编写、调试和部署软件应用程序。 我们在编写完接口代码后需要进行接口调试等操作&#xff0c;一般需要打开额外的调试工具。今天就给大家介绍一款IDEA插件&#xff…

SpringCloud(H版alibaba)框架开发教程之nacos做配置中心——附源码(2)

上篇主要讲了使用eureka&#xff0c;zk&#xff0c;nacos当注册中心 这篇内容是nacos配置中心 代码改动部分mysql驱动更新到8.0&#xff0c;数据库版本升级到了8.0&#xff0c;nacos版本更新到了2.x nacos2.x链接 链接&#xff1a;https://pan.baidu.com/s/11nObzgTjWisAfOp…

工程(十七)——自己数据集跑R2live

博主创建了一个科研互助群Q&#xff1a;772356582&#xff0c;欢迎大家加入讨论。 r2live是比较早的算法&#xff0c;编译过程有很多问题&#xff0c;通过以下两个博客可以解决 编译R2LIVE问题&解决方法-CSDN博客 r2live process has died 问题解决了_required process …

Kafka安装及简单使用介绍

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

鸿蒙HarmonyOS-带笔锋手写板(三)

笔者用ArkTS 写了一个简单的带笔锋的手写板应用&#xff0c;并且可以将手写内容保存为图片。 一、效果图 手写效果如下&#xff08;在鸿蒙手机模拟器上运行&#xff0c;手写时反应可能会有点慢&#xff09; 二、实现方法 参考文章&#xff1a; 支持笔锋效果的手写签字控件_a…

【数据结构】详细剖析线性表

顺序表与链表的比较 导言一、线性表二、线性表的存储结构三、顺序表和链表的相同点四、顺序表与链表之间的差异五、存储结构的选择六、静态顺序表的基本操作七、无头结点单链表的基本操作结语 导言 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;&#xff0…

VStudio2022导出Qt项目在Linux的Qtcreator中运行修复错误记录

公司项目中的代码在VStudio2022中编写&#xff0c;交给我需要移植Linux的Qtcreator中&#xff0c;记录一下移植过程中的遇到的坑&#xff0c;按照错误顺序由高到低记录一下&#xff0c;边尝试边解决边记录&#xff0c;写作方面没有逻辑&#xff0c;每个人项目环境不一样&#x…

P1019 [NOIP2000 提高组] 单词接龙 刷题笔记

P1019 [NOIP2000 提高组] 单词接龙 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路来自 大佬 Chardo 的个人中心 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 匹配 &#xff1a; 将 第一个字符串末尾 和第二个字符串第一个开始匹配 如果 j<i这段走完了 flag还没…

【ROS2】MOMO的鱼香ROS2(二)ROS2入门篇——ROS2初体验

ROS2初体验 引言专业术语认识1 认识ROS21.1 ROS2版本对照表1.2 ROS与ROS2对比1.3 ROS2架构1.3.1 DDS实现层1.3.2 ROS中间件接口&#xff08;RMW&#xff09;1.3.3 ROS2客户端库 RCL 2 安装ROS22.1 ROS安装&#xff08;一键式&#xff09;2.2 手动安装ROS22.2.1 添加ROS软件源2.…

4.28 构建onnx结构模型-Unfold

前言 构建onnx方式通常有两种&#xff1a; 1、通过代码转换成onnx结构&#xff0c;比如pytorch —> onnx 2、通过onnx 自定义结点&#xff0c;图&#xff0c;生成onnx结构 本文主要是简单学习和使用两种不同onnx结构&#xff0c; 下面以 Unfold 结点进行分析 方式 方法…

鸿蒙(OpenHarmony)系统之智能语音部件(1)

本文重点参考&#xff1a; OpenHarmony/ai_intelligent_voice_framework 一、总体概述 1. 功能简介及架构 智能语音组件包括智能语音服务框架和智能语音驱动&#xff0c;主要实现了语音注册及语音唤醒相关功能。 智能语音组件架构图如下图所示&#xff1a; &#xff08;1&a…

【ONE·MySQL || 数据类型 表的约束】

总言 主要内容&#xff1a;介绍MySQL中的常见数据类型&#xff08;数值类型、文本二进制类型、时间日期、字符串类型&#xff09;&#xff0c;以及对表的约束&#xff08;非空约束、默认约束、列描述、零填充约束、自增长约束、主键约束、唯一键约束、外键约束&#xff09;。  …

详解维吉尼亚密码(附四种攻击策略)

目录 一. 介绍 二. 破解维吉尼亚密码 2.1 频率统计 2.2 提高型频率统计法 2.3 Kasiski攻击法 2.4 重合指数攻击法&#xff08;index of coincidence method&#xff09; 三. 小结 一. 介绍 我们知道英语字母的出现频率是有规律的&#xff0c;比如像下表&#xff1a; 掌…

2023-12-23 LeetCode每日一题(移除石子使总数最小)

2023-12-23每日一题 一、题目编号 1962. 移除石子使总数最小二、题目链接 点击跳转到题目位置 三、题目描述 给你一个整数数组 piles &#xff0c;数组 下标从 0 开始 &#xff0c;其中 piles[i] 表示第 i 堆石子中的石子数量。另给你一个整数 k &#xff0c;请你执行下述…

2024任务驱动Java程序设计讲课提纲

文章目录 为何采用任务驱动&#xff1f;任务驱动Java程序设计课程概述项目一&#xff1a;踏上Java开发之旅任务1&#xff1a;安装配置JDK并开发第一个Java程序1、安装JDK2、配置JDK环境变量3、开发第一个Java程序 任务2&#xff1a;搭建Java集成开发环境IntelliJ IDEA1、安装In…