我遇到了一个时间问题,从数据库中循环了100万个潜在的行。我基本上将行拉入DataTable并循环遍历它们,但它变慢了。有什么替代品?我可以将这些行拆分成像块一样的20,000块。我可以在C#中使用并行处理吗?基本上,代码循环遍历与特定查询匹配的每个潜在记录,并尝试确定它是否是合法条目。这就是每个记录需要单独访问的原因。一个对象的记录可能达到1000万行。方法似乎是多台计算机中的并行处理或具有多个内核的单机中的PP,或某种数据结构/方法的变化?
任何意见,想法和猜测都有助于使这一点快速合理?
答案 0 :(得分:2)
首先关闭:不要将DataTable
用于此类操作:
DataTable
并非一致。 再次:不要将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
}
}
执行处理代码时将阻止阅读器,这意味着不再从DB读取行
如果处理代码很重,那么使用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
}
}
答案 1 :(得分:0)
我建议使用双核机器进行并行循环,并尝试使用通用列表的每个循环,我认为这可能会使您的流程更快。