.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 相关文章推荐
浅析InnoDB索引结构
Apr 05 MySQL
MySQL获取所有分类的前N条记录
May 07 MySQL
超详细教你怎么升级Mysql的版本
May 19 MySQL
IDEA 链接Mysql数据库并执行查询操作的完整代码
May 20 MySQL
MySQL大小写敏感的注意事项
May 24 MySQL
MySQL完整性约束的定义与实例教程
May 30 MySQL
MySQL中几种插入和批量语句实例详解
Sep 14 MySQL
浅谈MySql整型索引和字符串索引失效或隐式转换问题
Nov 20 MySQL
全面盘点MySQL中的那些重要日志文件
Nov 27 MySQL
面试提问mysql一张表到底能存多少数据
Mar 13 MySQL
Mysql调整优化之四种分区方式以及组合分区
Apr 13 MySQL
mysql序号rownum行号实现方式
Dec 24 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
PHP编程中的__clone()方法使用详解
2015/11/27 PHP
理解PHP中的Session及对Session有效期的控制
2016/01/08 PHP
PHP简单获取上月、本月、近15天、近30天的方法示例
2017/07/03 PHP
PHP strripos函数用法总结
2019/02/11 PHP
PHP实现微信提现功能(微信商城)
2019/11/21 PHP
一款JavaScript压缩工具:X2JSCompactor
2007/06/13 Javascript
jQuery 扩展对input的一些操作方法
2009/10/30 Javascript
$.ajax返回的JSON无法执行success的解决方法
2011/09/09 Javascript
JavaScript模板入门介绍
2012/09/26 Javascript
使用Javascript实现选择下拉菜单互移并排序
2016/02/23 Javascript
jquery跟随屏幕滚动效果的实现代码
2016/04/13 Javascript
node.js cookie-parser 中间件介绍
2016/06/06 Javascript
利用transition实现文字上下抖动的效果
2017/01/21 Javascript
Angular2 之 路由与导航详细介绍
2017/05/26 Javascript
Angular.js通过自定义指令directive实现滑块滑动效果
2017/10/13 Javascript
pm2 部署 node的三种方法示例
2017/10/20 Javascript
基于elementUI使用v-model实现经纬度输入的vue组件
2019/05/12 Javascript
vue 开发企业微信整合案例分析
2019/12/02 Javascript
浅谈Vue组件单元测试究竟测试什么
2020/02/05 Javascript
详解Django中的form库的使用
2015/07/18 Python
Python 列表排序方法reverse、sort、sorted详解
2016/01/22 Python
用python代码将tiff图片存储到jpg的方法
2018/12/04 Python
树莓派+摄像头实现对移动物体的检测
2019/06/22 Python
opencv3/C++实现视频读取、视频写入
2019/12/11 Python
python scatter函数用法实例详解
2020/02/11 Python
pytorch 实现在一个优化器中设置多个网络参数的例子
2020/02/20 Python
Python 字节流,字符串,十六进制相互转换实例(binascii,bytes)
2020/05/11 Python
html5中为audio标签增加停止按钮动作实现方法
2013/01/04 HTML / CSS
Currentbody西班牙:美容仪专家
2019/09/28 全球购物
美国基督教约会网站:ChristianCafe.com
2020/02/04 全球购物
咖啡馆创业计划书
2014/01/26 职场文书
工厂会计员职责
2014/02/06 职场文书
2015年学校关工委工作总结
2015/04/03 职场文书
公司更名通知函
2015/04/24 职场文书
祝酒词范文
2015/08/12 职场文书
Rust 连接 PostgreSQL 数据库的详细过程
2022/01/22 PostgreSQL