我有一张大桌子,我想要清除旧记录。记录有一个字段'FilePath'。这里的'clear'表示将'FilePath'标记为null。问题是因为该表有数百万条记录,一次更新是不可能的。它炸毁了记忆。所以我的策略是每次获取2000行并更新它们然后继续处理下一个块。
我的查询:
int pageNumber = 0;
int pageSize = 2000;
bool hasHitEnd = false;
while (!hasHitEnd)
{
var size = pageNumber * pageSize;
var query = cdrContext.Mytable.Where(c => c.FacilityID == facilityID && c.FilePath != null && c.TimeStationOffHook < oldDate)
.OrderBy(c => c.TimeStationOffHook)
.Skip(size)
.Take(pageSize)
.Select(c => new { c.FilePath, c.FileName })
.ToList();
var q = cdrContext.Mytable.Where(c => c.FacilityID == facilityID && c.FilePath != null && c.TimeStationOffHook < oldDate)
.OrderBy(c => c.TimeStationOffHook)
.Skip(size)
.Take(pageSize)
.ToList();
foreach (var y in q)
{
y.FilePath = null;
}
cdrContext.SaveChanges();
if (query.Count() < pageSize)
{
hasHitEnd = true;
}
pageNumber++;
我对代码不太自信。因为在更新数据后,FilePath为null。然后在下一次运行中,它可能不会指向右侧的块,因为我跳过一个块。
我是否需要删除跳过部分?
答案 0 :(得分:1)
您不需要跳过记录,因为更新后的下一页将成为第一页(更新的项目将与您下次调用时的查询过滤器不匹配)。
// define query, but don't execute it
var query = cdrContext.Mytable.Where(c => c.FacilityID == facilityID &&
c.FilePath != null &&
c.TimeStationOffHook < oldDate)
.OrderBy(c => c.TimeStationOffHook)
.Take(pageSize);
List<Foo> itemsToUpdate = query.ToList(); // get first N items
while(itemsToUpdate.Any()) // all items updated
{
// update items
cdrContext.SaveChanges();
itemsToUpdate = query.ToList(); // get first N items
}
答案 1 :(得分:1)
无需跳过记录,后续页面将成为您的第一页。你也不需要两次查询数据库我看到你使用查询和q这是没有必要的。只需使用q它将有助于提高性能。您可以删除以下代码
if (query.Count() < pageSize)
{
hasHitEnd = true;
}
如果q.Count()== 0,则将其替换为q中的记录数,然后您可以中断循环或设置hasHitEnd = true;