MySqlBulkLoader一种高效的数据保存方案

在每天重复的日子里,不断发现新奇,便是生活的美好

06849602f0289fa9087a05e4d2d73ba6.jpeg

@图片:北京西山随拍 @摄影师:刘先生

最近在处理大批量数据入库的问题,认识了MySqlBulkLoader,这是一种可以高效地实现MySql数据保存入库的方案,分享给各位爱技术懂技术的小伙伴。

MySqlBulkLoader可以高效地将数据从CSV(或TSV)文件,Stream(流)加载到MySql数据表中。经不严格测试,在每次1万条数据的情况下,使用MySqlBulkLoader相比批量Insert语句的方式,效率提升1倍以上。

01 引入依赖包

根据项目的.net版本,引入相应版本的MySqlConnector依赖包

02 示例代码:从CSV文件加载数据

using var connection = new MySqlConnection("...;AllowLoadLocalInfile=True");
await connection.OpenAsync();
var bulkLoader = new MySqlBulkLoader(connection)
{
	FileName = @"C:\Path\To\file.csv",
	TableName = "destination",
	CharacterSet = "UTF8",
	NumberOfLinesToSkip = 1,
	FieldTerminator = ",",
	FieldQuotationCharacter = '"',
	FieldQuotationOptional = true,
	Local = true,
}
var rowCount = await bulkLoader.LoadAsync();

以上示例代码是从官网中复制出来的,大概做个解释。

FileName:csv文件本地路径

TableName:目标表表名

注意:数据库连接需要设置:AllowLoadLocalInfile=true

03 示例代码:从Stream加载数据

实际开发中,通过csv文件加载数据的场景较少,更多的是从程序中提取数据,直接入库保存,这可以通过Stream方式实现。

/// <summary>
/// 
/// </summary>
/// <returns></returns>
private async Task<int> BulkInnerSave(System.Data.Common.DbConnection dbConnection, List<AssessmentDetailSummary> assessmentDetail)
{
	int rowCount = 0;
	if (assessmentDetail.Any())
	{
		using var memoryStream = new MemoryStream();
		foreach (var item in assessmentDetail)
		{
			var bytes =
			Encoding.UTF8.GetBytes($"{item.NumericalOrder},{item.ProductID}\r\n");
			memoryStream.Write(bytes, 0, bytes.Length);
		}

		var columns = new string[] { "NumericalOrder", "ProductID"};
		rowCount = await InnerBulkSave(dbConnection, memoryStream, "assessment_detail", columns);
	}

	return rowCount;
}
//
private async Task<int> InnerBulkSave(System.Data.Common.DbConnection dbConnection, MemoryStream memoryStream, string tableName, string[] columns)
{
	memoryStream.Position = 0;

	var connection = dbConnection as MySqlConnection;
	if (connection.State != ConnectionState.Open)
	{
		await connection.OpenAsync();
	}

	MySqlBulkLoader bl = new MySqlBulkLoader(connection)
	{
		SourceStream = memoryStream,
		TableName = tableName,
		NumberOfLinesToSkip = 0,
		FieldTerminator = ",",
		FieldQuotationCharacter = '"',
		FieldQuotationOptional = true,
		Local = true,
	};
	bl.Columns.AddRange(columns);
	return await bl.LoadAsync();
}

与加载csv文件的差别在于,FileName属性改成了SourceStream,而SourceStream的内容格式和csv文件是一样的。

另外要说明一下属性Columns,这是一个可选项,相当于Insert语句中指定的列名,目的是指定csv文件或Stream中的数据对应的列。

04 在EF中使用Bulk操作

由于本次项目中并没有使用EF,所以采用了直接调用MySqlBulkLoader这种原始的方式,如果你的项目中使用了EF框架,可以引用包:EFCore.BulkExtensions或者EFCore.BulkExtensions.MySql,调用DbContext的扩展方法,更简便地实现批量保存。

context.BulkInsert(entities);    
context.BulkSaveChanges();

各位热爱技术的小伙伴,你是否希望在下一个项目中,尝试一下这种方式。

喜欢此内容的朋友可以点赞,转发,关注

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值