经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MySQL » 查看文章
.Net Core导入千万级数据至Mysql的步骤
来源:jb51  时间:2021/5/24 12:12:35  对本文有异议

前期准备

订单测试表

  1. CREATE TABLE `trade` (
  2.   `id` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
  3.   `trade_no` VARCHAR(50) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
  4.   UNIQUE INDEX `id` (`id`),
  5.   INDEX `trade_no` (`trade_no`)
  6. )
  7. COMMENT='订单'
  8. COLLATE='utf8_unicode_ci'
  9. ENGINE=InnoDB;

测试环境

操作系统:Window 10 专业版

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

内存:16G

MySQL版本:5.7.26

实现方法:

1、单条数据插入

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

 实现代码:

  1. //开始时间
  2. var startTime = DateTime.Now;
  3. using (var conn = new MySqlConnection(connsql))
  4. {
  5.     conn.Open();
  6.     //插入10万数据
  7.     for (var i = 0; i < 100000; i++)
  8.     {
  9.         //插入
  10.         var sql = string.Format("insert into trade(id,trade_no) values('{0}','{1}');",
  11.             Guid.NewGuid().ToString(), "trade_" + (i + 1)
  12.             );
  13.         var sqlComm = new MySqlCommand();
  14.         sqlComm.Connection = conn;
  15.         sqlComm.CommandText = sql;
  16.         sqlComm.ExecuteNonQuery();
  17.         sqlComm.Dispose();
  18.     }
  19.     conn.Close();
  20. }
  21. //完成时间
  22. var endTime = DateTime.Now;
  23. //耗时
  24. var spanTime = endTime - startTime;
  25. Console.WriteLine("循环插入方式耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");

10万条测试耗时:

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

  1. //开始时间
  2. var startTime = DateTime.Now;
  3. using (var conn = new MySqlConnection(connsql))
  4. {
  5.     conn.Open();
  6.     //插入10万数据
  7.     var sql = new StringBuilder();
  8.     for (var i = 0; i < 100000; i++)
  9.     {
  10.         //插入
  11.         sql.AppendFormat("insert into trade(id,trade_no) values('{0}','{1}');",
  12.             Guid.NewGuid().ToString(), "trade_" + (i + 1)
  13.             );
  14.         //合并插入
  15.         if (i % 1000 == 999)
  16.         {
  17.             var sqlComm = new MySqlCommand();
  18.             sqlComm.Connection = conn;
  19.             sqlComm.CommandText = sql.ToString();
  20.             sqlComm.ExecuteNonQuery();
  21.             sqlComm.Dispose();
  22.             sql.Clear();
  23.         }
  24.     }
  25.     conn.Close();
  26. }
  27. //完成时间
  28. var endTime = DateTime.Now;
  29. //耗时
  30. var spanTime = endTime - startTime;
  31. Console.WriteLine("循环插入方式耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");

10万条测试耗时:

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

2、合并数据插入

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

  1. //开始时间
  2. var startTime = DateTime.Now;
  3. using (var conn = new MySqlConnection(connsql))
  4. {
  5.     conn.Open();
  6.     //插入10万数据
  7.     var sql = new StringBuilder();
  8.     for (var i = 0; i < 100000; i++)
  9.     {
  10.         if (i % 1000 == 0)
  11.         {
  12.             sql.Append("insert into trade(id,trade_no) values");
  13.         }
  14.         //拼接
  15.         sql.AppendFormat("('{0}','{1}'),", Guid.NewGuid().ToString(), "trade_" + (i + 1));
  16.         //一次性插入1000条
  17.         if (i % 1000 == 999)
  18.         {
  19.             var sqlComm = new MySqlCommand();
  20.             sqlComm.Connection = conn;
  21.             sqlComm.CommandText = sql.ToString().TrimEnd(',');
  22.             sqlComm.ExecuteNonQuery();
  23.             sqlComm.Dispose();
  24.             sql.Clear();
  25.         }
  26.     }
  27.         
  28.     conn.Close();
  29. }
  30. //完成时间
  31. var endTime = DateTime.Now;
  32. //耗时
  33. var spanTime = endTime - startTime;
  34. Console.WriteLine("合并数据插入方式耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");

10万条测试耗时:

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

3、MySqlBulkLoader插入

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

实现代码:

  1. //开始时间
  2. var startTime = DateTime.Now;
  3. using (var conn = new MySqlConnection(connsql))
  4. {
  5.     conn.Open();
  6.     var table = new DataTable();
  7.     table.Columns.Add("id", typeof(string));
  8.     table.Columns.Add("trade_no", typeof(string));
  9.     //生成10万数据
  10.     for (var i = 0; i < 100000; i++)
  11.     {
  12.         if (i % 500000 == 0)
  13.         {
  14.             table.Rows.Clear();
  15.         }
  16.         //记录
  17.         var row = table.NewRow();
  18.         row[0] = Guid.NewGuid().ToString();
  19.         row[1] = "trade_" + (i + 1);
  20.         table.Rows.Add(row);
  21.         //50万条一批次插入
  22.         if (i % 500000 != 499999 && i < (100000 - 1))
  23.         {
  24.             continue;
  25.         }
  26.         Console.WriteLine("开始插入:" + i);
  27.         //数据转换为csv格式
  28.         var tradeCsv = DataTableToCsv(table);
  29.         var tradeFilePath = System.AppDomain.CurrentDomain.BaseDirectory + "trade.csv";
  30.         File.WriteAllText(tradeFilePath, tradeCsv);
  31.         #region 保存至数据库
  32.         var bulkCopy = new MySqlBulkLoader(conn)
  33.         {
  34.             FieldTerminator = ",",
  35.             FieldQuotationCharacter = '"',
  36.             EscapeCharacter = '"',
  37.             LineTerminator = "\r\n",
  38.             FileName = tradeFilePath,
  39.             NumberOfLinesToSkip = 0,
  40.             TableName = "trade"
  41.         };
  42.         bulkCopy.Columns.AddRange(table.Columns.Cast<DataColumn>().Select(colum => colum.ColumnName).ToList());
  43.         bulkCopy.Load();
  44.         #endregion
  45.     }
  46.     conn.Close();
  47. }
  48. //完成时间
  49. var endTime = DateTime.Now;
  50. //耗时
  51. var spanTime = endTime - startTime;
  52. Console.WriteLine("MySqlBulk方式耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");

10万条测试耗时:

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

secure_file_priv= 

性能测试对比

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

最后

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

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

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号