2012-06-25 2 views
3

최근 엔 Entity Framework에서 SQL Server 2008에 대해 쿼리하는 성능 문제가 발생했습니다. 문제를 해결할 수 있었지만 문제가 해결 된 이유를 알 수 없습니다. 나는 SQL에서 IN 절을 생성하기 위해 .Contains() 메소드와 함께 Guids 콜렉션을 사용하고있다. 여기에 원래 코드는 (테이블 이름이 무죄를 보호하기 위해 변경)입니다 :Entity Framework 동일한 결과를 갖는 두 개의 쿼리가 더 빠릅니다.

Guid[] values = filter.Split(',').Select<String, Guid>(d => new Guid(d)).ToArray(); 


returnValue = returnValue.Where(t => values.Contains(t.WorkItem.Requirement.Project.ProjectId)); 

이 쿼리는 150 ProjectID 년대가>있을 때 실행을 위해 ~ 20 초 소요됩니다. .Contains()의 위치를 ​​변경함으로써 나는 것들을 극적으로 빠르게 할 수있다. 다음은 리팩터입니다.

Guid[] values = filter.FilterValue.Split(',').Select<String, Guid>(d => new Guid(d)).ToArray(); 

var projects = from p in context.DC_DEF_Project 
       where values.Contains(p.ProjectId) 
       select p; 

returnValue = from t in returnValue 
       join p in projects on t.DC_DEF_ProjectWorkItem.DC_DEF_ProjectRequirement.ProjectId equals p.ProjectId 
       select t; 

이 코드는 위 쿼리와 동일한 데이터 세트에서 ~ 0.125 초가 소요됩니다.

확실한 이유가 있지만 내 호기심이 나를 죽이고 있습니다. 이게 뭐야?

+3

각 코드가 생성하는 sql은 무엇입니까? LOok을 읽고 differnces를보고 각각에 대한 실행 계획을보고 왜 다른 하나보다 느린 지 확인하십시오. – HLGEM

+0

프로파일 링 세션을 수행하고 두 쿼리에서 생성 된 실제 SQL을 비교하는 것이 좋습니다. –

+0

returnValue의 선언과 초기화를 보여줄 수 있습니까? 그 유형은 무엇입니까? – Odrade

답변

1

내 생각 엔 SQL에서 한 묶음 또는 OR을 사용하여 작업 항목의 외래 키에 대해 평가 된 결과가 두 번째 조인이 기본 키로 프로젝트에 조인하고 150 개의 ID 만 평가 한 후 다른 테이블에 조인합니다.

+0

Bill For The Win! 나는 두 가지 방법으로 윤곽을 잡았다. 속도가 느릴수록 .Contains의 각 항목에 대해 OR 절이있는 반면, 빠른 것은 내가 원래 둘 다 기대했던 것처럼 IN 절을 사용합니다. – SamuelWarren

+0

이 패턴은 무언가가 무작위로 EF를 통해 OR 재난이되는 프로젝트 중 하나에서 많이 나타납니다. 누군가가 이것에 대한 진정한 방아쇠/문지방을 찾으면 나는 또한 알고 싶어합니다. – Bill

0

첫 번째 예에서는 앱에 전체 데이터 세트를 가져 와서 메모리 내 linq 쿼리를 수행한다고 생각합니다.

+0

둘 다 IQueryable이라는 점을 감안할 때 LINQ2Objects에 대한 이유는 무엇입니까? – SamuelWarren

+1

아마 그렇지는 않지만 첫 번째 예제에서는 returnValue가 설정된 곳을 보지 못했습니다. 아마도 그것은 대신 IEnumberable을 구현합니까? – akatakritos

0

필자는 Linq의 작업을 이해하기 위해서는 쿼리의 지연된 실행과 관련이 있어야합니다. 당신의 고정 된 버전의

, 당신은 평가하고 다른 후 하나를 해석됩니다 두 가지의 LINQ 식을 가지고 있지만, 을 실행 한 번만 당신이 결과를 ( 어느 경우)를 열거 할 때. 깔끔하게 은 데이터베이스 액세스를 줄입니다.

첫 번째 버전 :

returnValue.Where(t => values.Contains(t.WorkItem.Requirement.Project.ProjectId)) 

하지 첫 번째 단계에서 어떤 필터링을 수행한다. 현재 테이블 행의 ProjectId의 테이블에 대해 values에 포함되어 있는지 확인합니다.

관련 문제