C# 相互处理150万行
我需要遍历150万行,对于行,我需要计算所有其他行的方差 目前我正在做一些类似的事情:C# 相互处理150万行,c#,sql-server-2008,preprocessor,sqlbulkcopy,C#,Sql Server 2008,Preprocessor,Sqlbulkcopy,我需要遍历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;
// 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
}
//模拟数据
var myTable=新数据表(“hello”);
添加(“ID”,typeof(int));
myTable.Columns.Add(“Value”,typeof(byte[]);
var random=新的random();
对于(int i=0;i<1000;i++)
{
var row=myTable.NewRow();
行[“ID”]=i;
var bitArray=新的bitArray(50*50);
对于(int j=0;j<50*50;j++)
{
Set(j,random.NextDouble()>=random.NextDouble());
}
byte[]byteArray=新字节[(int)Math.天花((double)bitArray.Length/8)];
CopyTo(byteArray,0);
行[“值”]=字节数组;
myTable.Rows.Add(row);
}
//模拟数据已完成。
计算风险值=新数据表(“计算”);
计算列。添加(“ID”,类型(int));
加上(“AaginstID”,typeof(int));
computed.Columns.Add(“ComputedIntersect”,typeof(byte[]);
computed.Columns.Add(“ComputedUnion”,typeof(byte[]);
for(int i=0;i
我使用打开TableLock的SQLBulkCopy存储数据,我的BatchSize是默认值(0-整批)。将150万条记录保存到数据库有点慢(30/60秒),因此我也愿意接受关于更改SQL存储机制的建议,但主要的瓶颈是C#。我的位数组的大小是2500位(我使用50*50作为网格,在代码中我允许可变网格大小,对于这个测试,假设它总是2500位)
对一行处理150万行大约需要140秒,这将花费太长的时间来处理所有内容,因此我需要找到更好的方法。为了在数据计数时更快地检索数据,我做了这么多的工作,所以我可以让它运行一天,但根据我的计算,这将需要将近三年的时间来处理
我将数据存储到外部循环的每个循环上的DB中,这样就不会一次在内存中保存太多数据。数据是以一种不切实际的方式设置的,我确实在第一轮处理中使用了BitArray.set(生成150万行),这是一个瓶颈,但不需要修改。主要目标是获得每一行与所有其他行的并集/交集,以便稍后我可以拉出相关行,准备开始。因此,如果有更好的存储类型(数据库中的二进制(313))或获得相同结果的更好方法,我愿意重写
我曾考虑过编写SQLCLR函数,但我也不确定这是正确的方法。预处理数据是必需的,因此我正在寻找最佳方法的帮助。我建议您在数据库中进行所有计算。SQL Server最擅长基于集合的操作,这使得它非常适合处理这些类型的问题。我简要介绍了您可以采取的步骤
30秒对我来说似乎是合理的,这是30秒,只为DB的保存,我知道我可以通过将它分块下来,我可以把DB保存到10秒左右(我在30秒内保存了更多的数据)。但问题是处理一行数据需要140秒(110秒)的时间。这需要三年才能完成,我没有那么多时间!Lol您将如何在SQL Server中计算这种类型的数据(二进制交集/并集)?你将如何穿过所有150万行?步骤1.3就是我现在正在做的。第二步是我需要帮助的“神奇”步骤。您将如何处理这些信息?正如我所说,我可以使用CLR,但同样,我可以使用游标、函数或计算视图等。我需要帮助找出最有效的方法。希望我听起来不是忘恩负义(我很感激),我只是想清楚我在寻找什么…用示例数据解释计算值,然后我可以向您展示SQL的功能。每行代表一个网格,每个网格(2500位)可以有任意数量的位开/关,我正在处理的1625625行都是这种网格的独特变体。我试图存储两个网格(二进制)的交点和并集,以便以后进行更复杂的计算。我已经在我的问题中加入了一个工作应用程序,它显示了示例数据(为您动态生成)。我很乐意为您提供更多的数据,您能告诉我您到底需要什么吗?我很高兴为你做点什么。。。