3

我在从数据库中循环遍历 100 万个潜在行时遇到了时间问题。我基本上将行拉入 DataTable 并循环遍历它们,但它变得越来越慢。那里有什么替代方案?我可以将这些行分成块,比如每块 20,000 个。我可以在 C# 中使用并行处理吗?基本上,代码会遍历与某个查询匹配的每条潜在记录,并尝试确定它是否是合法条目。这就是为什么需要单独访问每条记录的原因。一个对象的记录可能达到 1000 万行。方法看起来像是多台计算机中的并行处理或具有多核的单台机器中的 PP,或者某种数据结构/方法的变化?

有什么意见、想法和猜测有助于使这个快速合理吗?

4

2 回答 2

2

首先:不要DataTable用于这样的操作

  • 很慢
  • 它消耗太多内存
  • 你需要等待很长时间才能真正开始处理数据
    • 在此期间,额外的核心什么也不做,因为将数据读入 aDataTable没有被并行化。
    • 此外,在读取数据时,CPU 通常几乎没有得到充分利用,因为网络或其他 I/O 延迟通常是主要因素。

再说一遍:不要DataTable用于这样的操作。

而是使用DataReader. 这使您可以立即开始使用/处理数据,而不是等待它被加载。最简单的版本是(MS SQL Server 示例):

var command = new SqlCommand()
{
  CommandText = "SELECT * FROM Table";
  Connection = new SqlConnection("InsertConnectionString");
};

using(var reader = command.ExecuteReader())
{
  while(reader.Read())
  {
    var values = new object[reader.FieldCount];
    reader.GetValues(values);

    // process values of row
  }
}

在执行您的处理代码时,阅读器将被阻止,这意味着不再从数据库中读取行。
如果处理代码很繁重,使用该库创建执行检查的任务可能是值得Task的,这将使您能够使用多个内核。但是,创建一个 有一个开销Task,如果一个Task不包含足够的“工作”,您可以将几行批处理在一起:

public void ReadData()
{
  var taskList = new List<Task<SomeResultType>>();

  var command = new SqlCommand()
  {
    CommandText = "SELECT * FROM Table";
    Connection = new SqlConnection("InsertConnectionString");
  };
  using(var reader = command.ExecuteReader())
  {
    var valueList = new List<object[]>(100);
    while(reader.Read())
    {
      var values = new object[reader.FieldCount];
      reader.GetValues(values);

      valueList.Add(values);

      if(valueList.Count == 100)
      {
        var localValueList = valueList.ToList();
        valueList.Clear();

        taskList.Add(Task<SomeResultType>.Factory.StartNew(() => Process(localValueList));
      }
    }
    if(valueList.Count > 0)
      taskList.Add(Task<SomeResultType>.Factory.StartNew(() => Process(valueList));
  }

  // this line completes when all tasks are done
  Task.WaitAll(taskList.ToArray());
}

public SomeResultType Process(List<object[]> valueList)
{
  foreach(var vals in valueList)
  {
    // put your processing code here, be sure to synchronize your actions properly
  }  
}
  • 批量大小(当前为 100)取决于正在完成的实际处理,可能需要进行调整。
  • 同步有它自己的挑战,你需要非常小心共享资源
于 2012-03-11T01:54:49.757 回答
0

我建议使用双核机器进行并行循环,并尝试将每个循环与通用列表一起使用,我认为这可能会使您的过程更快。

于 2012-03-11T01:55:07.560 回答