2013-07-31 3 views
1

이 Linq에 매우 느리다 (제공 예 참조) 그 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(); 

유일한 변화의 배를 가속입니다 I 결과를 새 변수에 직접 저장하고 LINQ 쿼리 (필요할 때 계산해야 함) 대신이 값으로 where 절을 만듭니다. 하지만 LINQ가 잘못 계산 한 것 같아요, 아니면 제가 잘못하고있는 것 같습니까? 내 데이터의 다음

일부 값이 모든 iedrDataRecordIDs 수집을 평가하고 있기 때문에

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; 
} 

왜 당신은 요구하고

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 

답변

3

시간은 FirstOrDefault입니다. 이것은 구체적인 객체가 아니며 열거 형 세트입니다. 이것은 실제로 일부 객체를 반환하는 함수입니다. 쿼리 할 때마다 함수가 호출되고 실행 비용을 지불하게됩니다.

당신이

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

을 변경 한 다음 사용하는 경우 recordIDs.FirstOrDefault() 당신은 엄청난 성능 향상을 볼 수 있습니다.

+0

To37() List 을 만드는 방법을 알려주세요. 그게 너무 비싸지 않습니까? – UNeverNo

+0

첫 번째 항목 만 필요한 경우 첫 번째 항목을 선택하십시오 (두 번째, 더 빠른 수행 예제). 나는 당신이 당신이 어떤 점에서 확인하는 모든 항목을 필요로한다고 생각했다. 그렇지 않으면 왜 IEnumerable을 생성 하는가? –

+0

re : "비용이 너무 많이들"- 많은 * 것들에 달려 있지만 항목이 이미 메모리에 있다면 엄청난 양의 메모리 (참고 문헌 만)도 시간도 낭비되지 않습니다. 나의 충고는 당신이해야 할 것에 초점을 맞추는 것입니다! 첫 번째 항목 만 필요하면 첫 번째 항목을 가져 와서 로컬 변수에 넣은 다음 'IEnumerable' 개체와 혼동하지 말고 사용하십시오. 모든 항목을 두 번 이상 반복해야하는 경우 목록에 넣으십시오. –

관련 문제