我需要经历150万行,对于行,我需要计算与所有其他行的差异。
目前,我正在做类似的事情:
// Mocked Data
var myTable = new DataTable("hello");
myTable.Columns.Add("ID", typeof (int));
myTable.Columns.Add("Value", typeof(byte[]));
var random = new Random();
for (int i = 0; i < 1000; i++)
{
var row = myTable.NewRow();
row["ID"] = i;
var bitArray = new BitArray(50 * 50);
for (int j = 0; j < 50*50; j++)
{
bitArray.Set(j, random.NextDouble() >= random.NextDouble());
}
byte[] byteArray = new byte[(int)Math.Ceiling((double)bitArray.Length / 8)];
bitArray.CopyTo(byteArray, 0);
row["Value"] = byteArray;
myTable.Rows.Add(row);
}
// Mocked data complete.
var calculated = new DataTable("calculated");
calculated.Columns.Add("ID", typeof (int));
calculated.Columns.Add("AaginstID", typeof (int));
calculated.Columns.Add("ComputedIntersect", typeof(byte[]));
calculated.Columns.Add("ComputedUnion", typeof(byte[]));
for (int i = 0; i < myTable.Rows.Count; i++)
{
for (int j = i + 1; j < myTable.Rows.Count; j++)
{
var row = calculated.NewRow();
row["ID"] = myTable.Rows[i]["ID"];
row["AaginstID"] = myTable.Rows[j]["ID"];
var intersectArray = new BitArray((byte[]) myTable.Rows[i]["Value"]);
var unionArray = new BitArray((byte[])myTable.Rows[i]["Value"]);
var jArray = new BitArray((byte[])myTable.Rows[j]["Value"]);
intersectArray.And(jArray);
unionArray.Or(jArray);
var intersectByteArray = new byte[(int)Math.Ceiling((double)intersectArray.Length / 8)];
var unionByteArray = new byte[(int)Math.Ceiling((double)unionArray.Length / 8)];
intersectArray.CopyTo(intersectByteArray, 0);
unionArray.CopyTo(unionByteArray, 0);
row["ComputedIntersect"] = intersectByteArray;
row["ComputedUnion"] = unionByteArray;
calculated.Rows.Add(row);
}
// Real data is 1.5m+ rows, so need to do this incrementally
// STORE DATA TO DB HERE
}
我使用带有TableLock的SQLBulkCopy存储我的数据,我的BatchSize是默认值(0 - 整批)。将150万条记录保存到数据库有点慢(30/60秒),所以我也对改变我的SQL存储机制的建议持开放态度,但主要的瓶颈是C#。我的BitArray大小为2500位(我使用50 * 50作为网格,在代码中我允许可变网格大小,对于此测试,假设它总是2500位)。
要对一行处理150万行大约需要140秒,处理所有内容需要很长时间,因此我需要找到更好的方法。正在进行这项工作是为了预先处理数据,以便在计算时更快地进行检索,因此我可以将其保留一天,但根据我的计算,这需要将近三年的时间来处理...
我将数据存储到外循环的每个循环上的DB中,这样我就不会立刻在内存中保留太多内容。数据以不切实际的方式设置,我确实使用BitArray.Set进行第一轮处理(生成150万行),这是一个瓶颈,但这并不需要修改。主要目标是使每一行的联盟/交集与所有其他行相对应,以便稍后我可以拉出相关的行,准备好了。因此,如果存在更好的存储类型(数据库中的二进制(313)),或者获得相同结果的更好方法,我可以重写。
我考虑过编写SQL CLR函数,但我不确定这是正确的方法。需要预先处理数据,所以我正在寻求最佳方法的帮助。
答案 0 :(得分:0)
我建议你在数据库中进行所有计算。 SQL Server最擅长基于集合的操作,这使得它非常适合这些类型的问题。我简要介绍了你可以采取的步骤