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(); 

唯一の変更点は、結果を新しい変数に直接格納し、LINQ クエリ (必要に応じて計算する必要があります) の代わりに、この値を使用して where 句を作成することです。しかし、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 に答える