相互处理150万行

时间:2013-10-07 21:33:03

标签: 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; 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函数,但我不确定这是正确的方法。需要预先处理数据,所以我正在寻求最佳方法的帮助。

1 个答案:

答案 0 :(得分:0)

我建议你在数据库中进行所有计算。 SQL Server最擅长基于集合的操作,这使得它非常适合这些类型的问题。我简要介绍了你可以采取的步骤

  1. 将您的所有数据bcp到临时表中。
  2. 使用您需要的计算值更新临时表。
  3. 插入“真实”表格,从临时表格中选择所需的值。