通过parallel.for

时间:2015-06-29 15:39:08

标签: c# sql-server task-parallel-library

需要从oracle下载大量数据(每天),然后删除sql server上的数据(如果是重新运行),然后使用sqlbulk copy将数据粘贴到sql server中。非并行版本:

     for (int i = 0; i < curves.Rows.Count; i++)
        {
                //download data from oracle
                var data = GetCurve(connectString, impdate, curves.Rows[i]);
                //delete old data in sql server
                DeleteSQL(DateTime.Now, curves.Rows[i]);
                //write to sql server with sqlbulk.copy
                writeCurve(data, "dbo.t_Curves");
}

我想使用parallel来提高速度,但显然这些步骤是相互依赖的。这就是我提出的(我之前从未使用过任务工厂):

Parallel.For(0, curves.Rows.Count, i =>
        {
                var taskLoad = Task.Factory.StartNew(() => GetCurve(connectString, impdate, curves.Rows[i]));
                var taskDelete = Task.Factory.StartNew(() => DeleteSQL(impdate, curves.Rows[i]));
                taskDelete.Wait();
                taskLoad.Wait();
                var taskWrite = Task.Factory.StartNew(() => writeCurve(taskLoad.Result, "dbo.t_Curves"));
  });

这大致是时间的一半。把时间减半我能期待什么?这是正确使用线程吗?这就是我能做的一切吗?我可以加入任何进一步的加速吗?

更新

仅供参考,Curves是一个带定义的数据表,我不是逐行编写或读取任何内容。

或者我应该这样写:

 Parallel.For(0, curves.Rows.Count, i =>
        {
                var taskLoad = Task.Factory.StartNew(() => GetCurve(connectString, impdate, curves.Rows[i]));
                var taskDelete = Task.Factory.StartNew(() => DeleteSQL(impdate, curves.Rows[i]));
                var res1 = await taskDelete;
                var res2 = await taskLoad;
                writeCurve(res2, "dbo.t_Curves");
  });

1 个答案:

答案 0 :(得分:1)

问:这是正确使用线程吗?

答:是的,你正在完成两项独立任务的昂贵工作,然后等待它们完成,然后继续完成。肯定+1给@jugarr指出你没有&最后一点工作还需要另一项任务

问:这是你可以做的吗?

*可能没有,从你正在做的事情的声音

  • 获得单行(来自Oracle)
  • 删除MSSQL中的单行(如果已存在)
  • 将单行添加回MSSQL

一些建议:

  • 批量处理,不要一次只使用一行。
  • 描述最慢的部分,是检索数据,删除数据还是插入数据?可能是这样的:
    • 使用单行,开始的开销 新的联系可能是巨大的。可能是那个
    • 尝试检索数据时缺少索引
    • 由于参照完整性而尝试删除数据时缺少索引

您获得的吞吐率是多少?多少MB / s?每条曲线是1MB还是1GB?