我的数据库中有 10 亿条记录,我需要用 20 个值随机更新所有行。
所以,对于每随机 5000 万条记录,需要更新 1 个值。
所以,我想到生成一个包含 10 亿个数字的列表,然后从该列表中随机选择 5000 万条记录,然后从该列表中删除这 5000 万条记录,等等。
我的代码:
列表创建:
List<long> LstMainList = new List<long>();
for (int i = 1; i <= 999999999; i++)
{
LstMainList.Add(i);
}
新空列表: List<TableData> Table1 = new List<TableData>();
选择随机数并将它们添加到新列表并从包含 10 亿个项目的主列表中删除项目。
Random rand = new Random();
for (int a = 0; a < 50000000; a++)
{
int lstindex = rand.Next(LstMainList.Count);
Int64 lstData = LstMainList[lstindex];
Table1.Add(new TableData { MESSAGE_ID = lstData });
LstMainList.RemoveAt(lstindex);
if (a % 100000 == 0)
{
if (previousThread != null)
{
previousThread.Join();
}
List<TableData> copyList = Table1.ToList();
previousThread = new Thread(() => BulkCopyList(copyList, "PLAN_TABLE_1"));
previousThread.Start();
Table1.Clear();
}
}
现在,我的问题是:在 LstMainList.RemoveAt(lstindex);
行,从 MainList 中删除索引需要很长时间,因为它包含 10 亿条记录。
有没有一种简单的方法可以从列表中删除记录?或任何其他方式使这变得简单?
最佳答案
首先 - 使用 array 作为 id 而不是 list(特别是没有初始化容量)
int idsCount = 100000000;
long[] ids = new long[idsCount];
for(long i = 1; i < idsCount; i++)
ids[i] = i;
使用Fisher–Yates随机播放数组中的 ID
Random rnd = new Random();
int n = idsCount;
while(n > 1)
{
int k = rnd.Next(n);
n--;
long temp = ids[n];
ids[n] = ids[k];
ids[k] = temp;
}
使用随机排列的 ID,您无需修改 ID 列表。在随机位置移除项目是非常昂贵的操作。如果您删除位置 0 的项目,则应将整个列表复制到新数组。现在您可以迭代 ids 数组。
或者您可以使用 morelinq Batch创建批处理的 TableData 并批量处理它们:
int size = 100000;
foreach(var batch in ids.Batch(size, id => new TableData { MESSAGE_ID = id }))
{
var copyList = batch.ToList();
// ...
}
更新:因此您需要不同大小的批处理,您可以使用以下扩展方法从数组中获取项目范围:
public static IEnumerable<T> GetRange<T>(
this T[] array, int startIndex, int count)
{
for (int i = startIndex; i < startIndex + count; i++)
yield return array[i];
}
因此,从索引 20000 开始获取 5000 个 TableData 将如下所示:
var copyList = ids.GetRange(20000, 5000)
.Select(id => new TableData { MESSAGE_ID = id })
.ToList();
当然,更有效的方法是迭代 ids 数组,并将项目添加到具有预初始化容量的列表中:
int size = 5000;
int startIndex = 20000;
List<TableData> copyList = new List<TableData>(size);
for (int i = startIndex; i < startIndex + size; i++)
copyList.Add(new TableData { MESSAGE_ID = ids[i] });
更进一步,我会将 TableData 对象的创建移动到执行批量复制的线程。并且刚刚传递了它应该使用的 ID 序列。
关于c# - 列表的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25198419/