我正在尝试导入大约900K行的数据并将其映射到我的新数据模型。 我的问题是我为这个导入功能构建的控制台应用程序会随着时间的推移而减慢。
我监控了SQL查询,它们都运行良好(<5ms)。 我试图一次导入较小的块,fx 1K行。 秒表计时如下:
当使用1K行的新块重新启动应用程序时,时序相似。
导入数据的格式如下:
public class ImportData
{
public int Id { get; set; }
public int TaxpayerId { get; set; }
public string CustomerName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get;set; }
}
我的数据模型的简化示例如下所示:
public class Channel
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Permission
{
public Guid Id { get; set; }
public Channel Channel { get; set; }
public string Recipient { get; set; }
}
public class Taxpayer
{
public Guid Id { get; set; }
public int TaxpayerId { get; set; }
public string Name { get; set; }
public List<Permission> Permissions { get; set; }
}
我的导入方法如下:
public void Import()
{
Stopwatch stopwatch = new Stopwatch();
//Get import data
List<ImportData> importDataList = _dal.GetImportData();
stopwatch.Start();
for (int i = 0; i < importDataList.Count; i++)
{
ImportData importData = importDataList[i];
Taxpayer taxpayer = new Taxpayer()
{
Name = importData.CustomerName,
TaxpayerId = importData.TaxpayerId,
Permissions = new List<Permission>()
};
//Does not call SaveChanges on the context
CreateTaxpayer(taxpayer, false);
//Create permissions
if (!string.IsNullOrWhiteSpace(importData.Email))
{
//Does not call SaveChanges on the context
CreatePermission(_channelIdEmail, importData.Email, taxpayer, PermissionLogType.PermissionRequestAccepted);
}
if (!string.IsNullOrWhiteSpace(importData.PhoneNumber))
{
//Does not call SaveChanges on the context
CreatePermission(_channelIdPhoneCall, importData.PhoneNumber, taxpayer, PermissionLogType.PermissionRequestAccepted);
//Does not call SaveChanges on the context
CreatePermission(_channelIdSms, importData.PhoneNumber, taxpayer, PermissionLogType.PermissionRequestAccepted);
}
if ((i + 1) % 100 == 0)
{
Console.WriteLine("Count: " + (i + 1) + " | Avg ms: " + stopwatch.ElapsedMilliseconds / 100);
stopwatch.Restart();
}
}
_dal.SaveChanges();
}
我尝试了以下内容:
我的想法已经不多了。你们有什么建议来解决这个性能问题吗?
答案 0 :(得分:0)
为什么不使用BulkCopy,此代码需要修改您的特定表格&amp;专栏,但希望你明白这个想法:
using (var bulkCopy = new SqlBulkCopy(_DbContext.Database.Connection.ConnectionString, SqlBulkCopyOptions.TableLock))
{
bulkCopy.BulkCopyTimeout = 1200; // 20 minutes
bulkCopy.BatchSize = 10000;
bulkCopy.DestinationTableName = "TaxPayer";
var table = new DataTable();
var props = TypeDescriptor.GetProperties(typeof(TaxPayer))
//Dirty hack to make sure we only have system data types
//i.e. filter out the relationships/collections
.Cast<PropertyDescriptor>()
.Where(propertyInfo => propertyInfo.PropertyType.Namespace.Equals("System"))
.ToArray();
foreach (var propertyInfo in props)
{
bulkCopy.ColumnMappings.Add(propertyInfo.Name, propertyInfo.Name);
table.Columns.Add(propertyInfo.Name, Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType);
}
// need to amend next line to account for the correct number of columns
var values = new object[props.Length + 1];
foreach (var item in importDataList)
{
for (var i = 0; i < values.Length - 1; i++)
{
///TODO: Decide which columns need including
values[i] = props[i].GetValue(item);
}
table.Rows.Add(values);
}
bulkCopy.WriteToServer(table);
}