C# 在大型数据表中优化LINQ
我有一个DataTable,它大约有800000行,由4列组成。起始位置、结束位置、距离和区域。我想做的是,对于特定区域中的每条记录,获取“相反”的记录,看看距离是否小于原始距离。此数据表中的每条记录都将有一条“相反”的记录 示例行及其“反面”如下所示:C# 在大型数据表中优化LINQ,c#,performance,linq,datatable,C#,Performance,Linq,Datatable,我有一个DataTable,它大约有800000行,由4列组成。起始位置、结束位置、距离和区域。我想做的是,对于特定区域中的每条记录,获取“相反”的记录,看看距离是否小于原始距离。此数据表中的每条记录都将有一条“相反”的记录 示例行及其“反面”如下所示: StartLoc | EndLoc | Distance | Zone 2, 1 4, 3 5 1 4, 3 2, 1 4 1 这里的问题是,当前的解决方案非常耗时
StartLoc | EndLoc | Distance | Zone
2, 1 4, 3 5 1
4, 3 2, 1 4 1
这里的问题是,当前的解决方案非常耗时且简单。下面的代码是目前采用的策略
public DataTable ProcessTable(DataTable _tbl)
{
//copy the schema to new datatable
DataTable ProcessedTable = _tbl.Clone();
foreach (DataRow row in _tbl.Rows)
{
var ReverseRow = from DataRow revRow in _tbl.Rows
where revRow.Field<string>("StartLoc") == row.Field<string>("EndLoc")
where revRow.Field<string>("EndLoc") == row.Field<string>("StartLoc")
where revRow.Field<string>("Zone") == row.Field<string>("Zone")
select revRow;
DataRow result = ReverseRow.First<DataRow>();
int rowDistance = row.Field<int>("Distance");
int resultDistance = result.Field<int>("Distance");
if (resultDistance < rowDistance)
row["Distance"] = resultDistance;
ProcessedTable.Rows.Add(row.ItemArray);
}
return ProcessedTable;
}
public DataTable ProcessTable(DataTable\u tbl)
{
//将架构复制到新的datatable
DataTable ProcessedTable=_tbl.Clone();
foreach(数据行中的数据行)
{
var ReverseRow=来自数据行revRow in _tbl.Rows
其中revRow.Field(“EndLoc”)==row.Field(“EndLoc”)
其中revRow.Field(“EndLoc”)==row.Field(“EndLoc”)
其中revRow.Field(“区域”)==row.Field(“区域”)
选择revRow;
DataRow结果=ReverseRow.First();
int rowdance=行字段(“距离”);
int resultDistance=结果字段(“距离”);
如果(结果距离<行距离)
行[“距离”]=结果距离;
ProcessedTable.Rows.Add(row.ItemArray);
}
返回可处理;
}
我是LINQ noobie,所以这个问题有三个部分:
尝试加入。您正在克隆整个表,这可能是速度慢的原因
public DataTable ProcessTable(DataTable _tbl)
{
//copy the schema to new datatable
var query = from r1 in _tbl.AsEnumerable()
from r2 in _tbl.AsEnumerable()
where (r1.Field<string>("StartLoc") == r2.Field<string>("EndLoc"))
&& (r1.Field<string>("EndLoc") == r2.Field<string>("StartLoc"))
&& (r1.Field<string>("Zone") == r2.Field<string>("Zone"))
select new { r1 = r1, r2 = r2 };
DataTable processedTable = query.Where(x => x.r1.Field<int>("Distance") < x.r2.Field<int>("Distance"))
.Select(x => x.r1)
.CopyToDataTable();
return processedTable;
}
public DataTable ProcessTable(DataTable\u tbl)
{
//将架构复制到新的datatable
var query=从r1开始,在_tbl.AsEnumerable()中
从r2开始,可计算()
式中(r1.字段(“终止点”)==r2.字段(“终止点”))
&&(r1.字段(“EndLoc”)==r2.字段(“STARTOC”))
&&(r1.字段(“区域”)==r2.字段(“区域”))
选择新的{r1=r1,r2=r2};
DataTable processedTable=query.Where(x=>x.r1.Field(“距离”)x.r1)
.CopyToDataTable();
返回可处理;
}
尝试加入。您正在克隆整个表,这可能是速度慢的原因
public DataTable ProcessTable(DataTable _tbl)
{
//copy the schema to new datatable
var query = from r1 in _tbl.AsEnumerable()
from r2 in _tbl.AsEnumerable()
where (r1.Field<string>("StartLoc") == r2.Field<string>("EndLoc"))
&& (r1.Field<string>("EndLoc") == r2.Field<string>("StartLoc"))
&& (r1.Field<string>("Zone") == r2.Field<string>("Zone"))
select new { r1 = r1, r2 = r2 };
DataTable processedTable = query.Where(x => x.r1.Field<int>("Distance") < x.r2.Field<int>("Distance"))
.Select(x => x.r1)
.CopyToDataTable();
return processedTable;
}
public DataTable ProcessTable(DataTable\u tbl)
{
//将架构复制到新的datatable
var query=从r1开始,在_tbl.AsEnumerable()中
从r2开始,可计算()
式中(r1.字段(“终止点”)==r2.字段(“终止点”))
&&(r1.字段(“EndLoc”)==r2.字段(“STARTOC”))
&&(r1.字段(“区域”)==r2.字段(“区域”))
选择新的{r1=r1,r2=r2};
DataTable processedTable=query.Where(x=>x.r1.Field(“距离”)x.r1)
.CopyToDataTable();
返回可处理;
}
欢迎光临。这个问题在另一个Stack Exchange站点上可能会更好。也许是代码审查?任何人祝你好运你能考虑StasLoC/EndoLC/Stand独特的组合吗?您可以在它们上添加一个主键,并使用Find获得良好的性能。每对数据只需查询一次,无需解决数据一致性问题。如果从数据库获取DataTable,则应在数据库上执行查询,而不是获取整个表。欢迎使用。这个问题在另一个Stack Exchange站点上可能会更好。也许是代码审查?任何人祝你好运你能考虑StasLoC/EndoLC/Stand独特的组合吗?您可以在它们上添加一个主键,并使用Find获得良好的性能。每对数据只需一次,无需解决数据一致性问题。如果从数据库获取DataTable,则应在数据库上执行查询,而不是获取整个表。基本上就是这样。但是,为了使它更精确,您可以考虑从OP查询中添加其他条件到连接(也显示如何执行复合键连接)。谢谢您的快速响应,我现在得到内存不足的异常。有什么建议吗?你可以试着一次只得到一个区域。或者回到慢法。如果数据来自使用存储过程的SQL Server,则速度会更快。查询缺少基本条件,如果他以这种形式尝试,难怪它会返回废话,甚至崩溃。Ivan Stoev已经指出了这一点。OP在连接中有三个条件:a.startoc==b.EndLoc
,a.EndLoc==b.startoc
,a.Zone==b.Zone
。你只有第一个。您并不是将每个记录与相反的记录进行比较,而是与更多的记录进行比较。而不是400000对,你可以很容易地像400000000对和最糟糕的,结果是不正确的。基本上就是这样。但是,为了使它更精确,您可以考虑从OP查询中添加其他条件到连接(也显示如何执行复合键连接)。谢谢您的快速响应,我现在得到内存不足的异常。有什么建议吗?你可以试着一次只得到一个区域。或者回到慢法。如果数据来自使用存储过程的SQL Server,则速度会更快。如果查询缺少基本条件,则