1

这个 Linq 很慢:

IEnumerable<string> iedrDataRecordIDs = dt1.AsEnumerable()
    .Where(x => x.Field<string>(InputDataSet.Column_Arguments_Name) == sArgumentName 
         && x.Field<string>(InputDataSet.Column_Arguments_Value) == sArgumentValue)
    .Select(x => x.Field<string>(InputDataSet.Column_Arguments_RecordID));

IEnumerable<string> iedrDataRecordIDs_Filtered = dt2.AsEnumerable()
    .Where(x => iedrDataRecordIDs.Contains(
                 x.Field<string>(InputDataSet.Column_DataRecordFields_RecordID)) 
             && x.Field<string>(InputDataSet.Column_DataRecordFields_Field) 
                 == sDataRecordFieldField 
             && x.Field<string>(InputDataSet.Column_DataRecordFields_Value) 
                 == sDataRecordFieldValue)
    .Select(x => x.Field<string>(InputDataSet.Column_DataRecordFields_RecordID));

IEnumerable<string> ieValue = dt2.AsEnumerable()
    .Where(x => x.Field<string>(InputDataSet.Column_DataRecordFields_RecordID) 
                == iedrDataRecordIDs_Filtered.FirstOrDefault() 
            && x.Field<string>(InputDataSet.Column_DataRecordFields_Field) == sFieldName)
    .Select(x => x.Field<string>(InputDataSet.Column_DataRecordFields_Value));

if (!ieValue.Any()) //very slow at this point
    return iedrDataRecordIDs_Filtered.FirstOrDefault();

这种变化将其加速了 10 倍或更多

string sRecordID = dt2.AsEnumerable()
    .Where(x => iedrDataRecordIDs.Contains(
            x.Field<string>(InputDataSet.Column_DataRecordFields_RecordID)) 
        && x.Field<string>(InputDataSet.Column_DataRecordFields_Field) 
            == sDataRecordFieldField 
        && x.Field<string>(InputDataSet.Column_DataRecordFields_Value) 
            == sDataRecordFieldValue)
    .Select(x => x.Field<string>(InputDataSet.Column_DataRecordFields_RecordID))
    .FirstOrDefault();

IEnumerable<string> ieValue = dt2.AsEnumerable()
   .Where(x => x.Field<string>(InputDataSet.Column_DataRecordFields_RecordID) == sRecordID 
        && x.Field<string>(InputDataSet.Column_DataRecordFields_Field) == sFieldName)
    .Select(x => x.Field<string>(InputDataSet.Column_DataRecordFields_Value));

if (!ieValue.Any()) //very fast at this point
    return iedrDataRecordIDs_Filtered.FirstOrDefault(); 

唯一的变化是我将结果直接存储在一个新变量中,并使用该值创建 where 子句,而不是 LINQ 查询(应在需要时计算)。但是 LINQ 似乎在这里以一种糟糕的方式计算它,还是我做错了什么?

这是我的数据的一些值

dt1.Rows.Count                     142 
dt1.Columns.Count                    3 
dt2.Rows.Count                     159 
dt2.Columns.Count                    3 
iedrDataRecordIDs.Count()            1 
iedrDataRecordIDs_Filtered.Count()   1 
ieValue.Count()                      1
4

1 回答 1

3

你问为什么

IEnumerable<string> iedrDataRecordIDs_Filtered = data;    
foreach (var item in collection)
{
    // do something with
    iedrDataRecordIDs_Filtered.FirstOrDefault();
}

string sRecordID = data.FirstOrDefault();
foreach (var item in collection)
{
    // do something with
    sRecordID;
}

很简单,因为您iedrDataRecordIDs每次获得FirstOrDefault. 这不是一个具体的对象,它是一个可枚举的集合。这实际上只是一个返回一些对象的函数。每次您查询它时,都会调用该函数,并且您将支付该执行成本。

如果你改变

IEnumerable<string> iedrDataRecordIDs_Filtered = dt2.AsEnumerable()... 
var recordIDs = iedrDataRecordIDs_Filtered.ToList();

然后使用recordIDs.FirstOrDefault()你会看到巨大的性能提升。

于 2013-07-31T17:28:19.600 回答