.Net Core导入千万级数据至Mysql的步骤


Posted in MySQL onMay 24, 2021

前期准备

订单测试表

CREATE TABLE `trade` (
  `id` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
  `trade_no` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
  UNIQUE INDEX `id` (`id`),
  INDEX `trade_no` (`trade_no`)
)
COMMENT='订单'
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB;

测试环境

操作系统:Window 10 专业版

CPU:Inter(R) Core(TM) i7-8650U CPU @1.90GHZ 2.11 GHZ

内存:16G

MySQL版本:5.7.26

实现方法:

1、单条数据插入

这是最普通的方式,通过循环一条一条的导入数据,这个方式的缺点很明显就是每一次都需要连接一次数据库。

 实现代码:

//开始时间
var startTime = DateTime.Now;
using (var conn = new MySqlConnection(connsql))
{
    conn.Open();
​
    //插入10万数据
    for (var i = 0; i < 100000; i++)
    {
        //插入
        var sql = string.Format("insert into trade(id,trade_no) values('{0}','{1}');",
            Guid.NewGuid().ToString(), "trade_" + (i + 1)
            );
        var sqlComm = new MySqlCommand();
        sqlComm.Connection = conn;
        sqlComm.CommandText = sql;
        sqlComm.ExecuteNonQuery();
        sqlComm.Dispose();
    }
​
    conn.Close();
}
​
//完成时间
var endTime = DateTime.Now;
​
//耗时
var spanTime = endTime - startTime;
Console.WriteLine("循环插入方式耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");

10万条测试耗时:

.Net Core导入千万级数据至Mysql的步骤

上面的例子,我们是批量导入10万条数据,需要连接10万次数据库。我们把SQL语句改为1000条拼接为1条,这样就能减少数据库连接,实现代码修改如下:

//开始时间
var startTime = DateTime.Now;
using (var conn = new MySqlConnection(connsql))
{
    conn.Open();
​
    //插入10万数据
    var sql = new StringBuilder();
    for (var i = 0; i < 100000; i++)
    {
        //插入
        sql.AppendFormat("insert into trade(id,trade_no) values('{0}','{1}');",
            Guid.NewGuid().ToString(), "trade_" + (i + 1)
            );
​
        //合并插入
        if (i % 1000 == 999)
        {
            var sqlComm = new MySqlCommand();
            sqlComm.Connection = conn;
            sqlComm.CommandText = sql.ToString();
            sqlComm.ExecuteNonQuery();
            sqlComm.Dispose();
            sql.Clear();
        }
    }
​
    conn.Close();
}
​
//完成时间
var endTime = DateTime.Now;
​
//耗时
var spanTime = endTime - startTime;
Console.WriteLine("循环插入方式耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");

10万条测试耗时:

.Net Core导入千万级数据至Mysql的步骤

通过优化后,原本需要10万次连接数据库,只需连接100次。从最终运行效果看,由于数据库是在同一台服务器,不涉及网络传输,性能提升不明显。

2、合并数据插入

在MySQL同样也支持,通过合并数据来实现批量数据导入。实现代码:

//开始时间
var startTime = DateTime.Now;
using (var conn = new MySqlConnection(connsql))
{
    conn.Open();
​
    //插入10万数据
    var sql = new StringBuilder();
    for (var i = 0; i < 100000; i++)
    {
        if (i % 1000 == 0)
        {
            sql.Append("insert into trade(id,trade_no) values");
        }
​
        //拼接
        sql.AppendFormat("('{0}','{1}'),", Guid.NewGuid().ToString(), "trade_" + (i + 1));
​
        //一次性插入1000条
        if (i % 1000 == 999)
        {
            var sqlComm = new MySqlCommand();
            sqlComm.Connection = conn;
            sqlComm.CommandText = sql.ToString().TrimEnd(',');
            sqlComm.ExecuteNonQuery();
            sqlComm.Dispose();
            sql.Clear();
        }
    }
        
​
    conn.Close();
}
​
//完成时间
var endTime = DateTime.Now;
​
//耗时
var spanTime = endTime - startTime;
Console.WriteLine("合并数据插入方式耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");

10万条测试耗时:

.Net Core导入千万级数据至Mysql的步骤

通过这种方式插入操作明显能够提高程序的插入效率。虽然第一种方法通过优化后,同样的可以减少数据库连接次数,但第二种方法:合并后日志量(MySQL的binlog和innodb的事务让日志)减少了,降低日志刷盘的数据量和频率,从而提高效率。同时也能减少SQL语句解析的次数,减少网络传输的IO。

3、MySqlBulkLoader插入

MySQLBulkLoader也称为LOAD DATA INFILE,它的原理是从文件读取数据。所以我们需要将我们的数据集保存到文件,然后再从文件里面读取。

实现代码:

//开始时间
var startTime = DateTime.Now;
using (var conn = new MySqlConnection(connsql))
{
    conn.Open();
    var table = new DataTable();
    table.Columns.Add("id", typeof(string));
    table.Columns.Add("trade_no", typeof(string));
​
    //生成10万数据
    for (var i = 0; i < 100000; i++)
    {
        if (i % 500000 == 0)
        {
            table.Rows.Clear();
        }
​
        //记录
        var row = table.NewRow();
        row[0] = Guid.NewGuid().ToString();
        row[1] = "trade_" + (i + 1);
        table.Rows.Add(row);
​
        //50万条一批次插入
        if (i % 500000 != 499999 && i < (100000 - 1))
        {
            continue;
        }
        Console.WriteLine("开始插入:" + i);
​
        //数据转换为csv格式
        var tradeCsv = DataTableToCsv(table);
        var tradeFilePath = System.AppDomain.CurrentDomain.BaseDirectory + "trade.csv";
        File.WriteAllText(tradeFilePath, tradeCsv);
​
        #region 保存至数据库
        var bulkCopy = new MySqlBulkLoader(conn)
        {
            FieldTerminator = ",",
            FieldQuotationCharacter = '"',
            EscapeCharacter = '"',
            LineTerminator = "\r\n",
            FileName = tradeFilePath,
            NumberOfLinesToSkip = 0,
            TableName = "trade"
        };
​
        bulkCopy.Columns.AddRange(table.Columns.Cast<DataColumn>().Select(colum => colum.ColumnName).ToList());
        bulkCopy.Load();
        #endregion
    }
​
    conn.Close();
}
​
//完成时间
var endTime = DateTime.Now;
​
//耗时
var spanTime = endTime - startTime;
Console.WriteLine("MySqlBulk方式耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");

10万条测试耗时:

.Net Core导入千万级数据至Mysql的步骤

注意:MySQL数据库配置需开启:允许文件导入。配置如下:

secure_file_priv= 

性能测试对比

针对上面三种方法,分别测试10万、20万、100万、1000万条数据记录,最终性能入如下:

.Net Core导入千万级数据至Mysql的步骤

最后

通过测试数据看,随着数据量的增大,MySqlBulkLoader的方式表现依旧良好,其他方式性能下降比较明显。MySqlBulkLoader的方式完全可以满足我们的需求。

以上就是.Net Core导入千万级数据至Mysql的步骤的详细内容,更多关于导入千万级数据至Mysql的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
MySQL InnoDB ReplicaSet(副本集)简单介绍
Apr 24 MySQL
Mysql服务添加 iptables防火墙策略的方案
Apr 29 MySQL
如何设计高效合理的MySQL查询语句
May 26 MySQL
MySQL 那些常见的错误设计规范,你都知道吗
Jul 16 MySQL
MySQL外键约束(FOREIGN KEY)案例讲解
Aug 23 MySQL
MySQL中连接查询和子查询的问题
Sep 04 MySQL
MySQL 用 limit 为什么会影响性能
Sep 15 MySQL
mysql事务隔离级别详情
Oct 24 MySQL
Mysql中有关Datetime和Timestamp的使用总结
Dec 06 MySQL
千万级用户系统SQL调优实战分享
Mar 03 MySQL
MySQL数据库如何给表设置约束详解
Mar 13 MySQL
MySQL查询日期时间
May 15 MySQL
MySQL大小写敏感的注意事项
May 24 #MySQL
MySQL 使用事件(Events)完成计划任务
May 24 #MySQL
MySQL触发器的使用
May 24 #MySQL
MySQL 重命名表的操作方法及注意事项
May 21 #MySQL
Mysql官方性能测试工具mysqlslap的使用简介
May 21 #MySQL
MySQL官方导出工具mysqlpump的使用
May 21 #MySQL
新手必备之MySQL msi版本下载安装图文详细教程
You might like
玩转虚拟域名◎+ .
2006/10/09 PHP
Discuz!下Memcache缓存实现方法
2010/05/28 PHP
采集邮箱的php代码(抓取网页中的邮箱地址)
2012/07/17 PHP
PHP中file_exists与is_file,is_dir的区别介绍
2012/09/12 PHP
Linux中用PHP判断程序运行状态的2个方法
2014/05/04 PHP
PHP获取一段文本显示点阵宽度和高度的方法
2015/03/12 PHP
php实现在限定区域里自动调整字体大小的类实例
2015/04/02 PHP
实现超用户体验 table排序javascript实现代码
2009/06/22 Javascript
js关闭父窗口时关闭子窗口
2013/04/01 Javascript
JavaScript判断一个字符串是否包含指定子字符串的方法
2015/03/18 Javascript
XML、HTML、CSS与JS的区别整理
2016/02/18 Javascript
原生JavaScript实现精美的淘宝轮播图效果示例【附demo源码下载】
2017/05/27 Javascript
在Debian(Raspberry Pi)树莓派上安装NodeJS的教程详解
2017/09/19 NodeJs
浅谈在vue项目中如何定义全局变量和全局函数
2017/10/24 Javascript
小程序接入腾讯位置服务的详细流程
2020/03/03 Javascript
在vue中嵌入外部网站的实现
2020/11/13 Javascript
[01:19]2014DOTA2国际邀请赛 采访TITAN战队ohaiyo 能赢DK很幸运
2014/07/12 DOTA
django框架之cookie/session的使用示例(小结)
2018/10/15 Python
Django rstful登陆认证并检查session是否过期代码实例
2019/08/13 Python
python随机生成库faker库api实例详解
2019/11/28 Python
Python自动化测试中yaml文件读取操作
2020/08/20 Python
一篇文章带你学习CSS3图片边框
2020/11/04 HTML / CSS
这段代码难道不该打印出56吗
2013/02/27 面试题
某公司.Net方向面试题
2014/04/24 面试题
心碎乌托邦的创业计划书范文
2013/12/26 职场文书
机械设计职业生涯规划书
2013/12/27 职场文书
《歌唱二小放牛郎》教学反思
2014/04/19 职场文书
《猴子种果树》教学反思
2014/04/26 职场文书
教师爱岗敬业演讲稿
2014/05/05 职场文书
幼儿园学前班幼儿评语
2014/12/29 职场文书
事业单位工作人员年度考核个人总结
2015/02/12 职场文书
七年级生物教学反思
2016/02/20 职场文书
Nginx服务器添加Systemd自定义服务过程解析
2021/03/31 Servers
centos8安装nginx1.9.1的详细过程
2021/08/02 Servers
vue使用localStorage持久性存储实现评论列表
2022/04/14 Vue.js
Pandas 数据编码的十种方法
2022/04/20 Python