【发布时间】:2016-11-16 03:01:19
【问题描述】:
我有一个将数据从旧数据库迁移到新数据库的导出作业。我遇到的问题是用户数量约为 300 万,而这项工作需要很长时间才能完成(15 多个小时)。我使用的机器只有 1 个处理器,所以我不确定 threading 是否是我应该做的。有人可以帮我优化这段代码吗?
static void ExportFromLegacy()
{
var usersQuery = _oldDb.users.Where(x =>
x.status == 'active');
int BatchSize = 1000;
var errorCount = 0;
var successCount = 0;
var batchCount = 0;
// Using MoreLinq's Batch for sequences
// https://www.nuget.org/packages/MoreLinq.Source.MoreEnumerable.Batch
foreach (IEnumerable<users> batch in usersQuery.Batch(BatchSize))
{
Console.WriteLine(String.Format("Batch count at {0}", batchCount));
batchCount++;
foreach(var user in batch)
{
try
{
var userData = _oldDb.userData.Where(x =>
x.user_id == user.user_id).ToList();
if (userData.Count > 0)
{
// Insert into table
var newData = new newData()
{
UserId = user.user_id; // shortened code for brevity.
};
_db.newUserData.Add(newData);
_db.SaveChanges();
// Insert item(s) into table
foreach (var item in userData.items)
{
if (!_db.userDataItems.Any(x => x.id == item.id)
{
var item = new Item()
{
UserId = user.user_id, // shortened code for brevity.
DataId = newData.id // id from object created above
};
_db.userDataItems.Add(item);
}
_db.SaveChanges();
successCount++;
}
}
}
catch(Exception ex)
{
errorCount++;
Console.WriteLine(String.Format("Error saving changes for user_id: {0} at {1}.", user.user_id.ToString(), DateTime.Now));
Console.WriteLine("Message: " + ex.Message);
Console.WriteLine("InnerException: " + ex.InnerException);
}
}
}
Console.WriteLine(String.Format("End at {0}...", DateTime.Now));
Console.WriteLine(String.Format("Successful imports: {0} | Errors: {1}", successCount, errorCount));
Console.WriteLine(String.Format("Total running time: {0}", (exportStart - DateTime.Now).ToString(@"hh\:mm\:ss")));
}
【问题讨论】:
-
您的研究表明了什么?不要将 EF 用于 ETL/批处理,回退到 SQL。例如,一个 MERGE 语句可能会有很大帮助。绝对不要在循环中调用 SaveChanges。这一切都假设数据库实际上是瓶颈,这意味着线程根本无法帮助您。
-
水晶球说旧数据库在 user_id 列上没有索引。你真的需要一个。如果由于某种原因这不切实际,请确保只读取旧数据库中的所有行一次。
-
先做一些分析。此外,并行化可能仍然有帮助,因为您可能会在数据库繁忙时做有用的 CPU 工作。
-
您是否考虑过使用 SQL Server Data Tools 执行迁移?
标签: c# multithreading entity-framework optimization