.Include () 대 EntityFramework의 .Load () 성능
당신이 나중에 코드에서의 탐색 속성에 액세스 할 필요가 큰 테이블을 쿼리 할 때 더 나은 무엇을 수행합니다 (I 명시 적으로 게으른 로딩을 사용하지 않음) .Include()또는 .Load()? 아니면 왜 다른 것을 사용합니까?
이 예에서 포함 된 테이블에는 모두 약 10 개의 항목 만 있고 직원은 약 200 개의 항목이 있으며, 대부분의 항목은 where 절과 일치하기 때문에 어쨌든 include로로드 될 수 있습니다.
Context.Measurements.Include(m => m.Product)
.Include(m => m.ProductVersion)
.Include(m => m.Line)
.Include(m => m.MeasureEmployee)
.Include(m => m.MeasurementType)
.Where(m => m.MeasurementTime >= DateTime.Now.AddDays(-1))
.ToList();
또는
Context.Products.Load();
Context.ProductVersions.Load();
Context.Lines.Load();
Context.Employees.Load();
Context.MeasurementType.Load();
Context.Measurements.Where(m => m.MeasurementTime >= DateTime.Now.AddDays(-1))
.ToList();
상황에 따라 다를 수 있습니다.
사용하는 경우 Include(), 당신은 얻을 이익 기본 데이터 저장소에 대한 단일 호출에 모든 데이터를 로딩한다. 예를 들어 이것이 원격 SQL Server 인 경우 성능이 크게 향상 될 수 있습니다.
단점 이다 Include()쿼리를 얻을하는 경향이 정말 복잡 당신이 (어떤 필터가 특히, Where()예를 들어, 전화) 또는 그룹을하려고합니다. EF는 원하는 데이터를 얻기 위해 하위 SELECT및 APPLY문을 사용하여 매우 많이 중첩 된 쿼리를 생성 합니다. 또한 훨씬 덜 효율적입니다. 가능한 모든 하위 개체 열이 포함 된 단일 데이터 행을 반환하므로 최상위 개체의 데이터가 여러 번 반복됩니다. (예를 들어 자식이 10 개인 단일 부모 개체는 부모 개체의 열에 대해 각각 동일한 데이터를 가진 10 개의 행을 생성합니다.) 단일 EF 쿼리가 너무 복잡해서 EF와 동시에 실행할 때 교착 상태 가 발생 했습니다. 로직 업데이트.
이 Load()방법은 훨씬 간단 합니다. 각 쿼리는 SELECT단일 테이블에 대한 쉽고 간단한 단일 문입니다. 이것들은 당신이 그들 중 많은 것을 (아마도 여러 번 더)해야하는 것을 제외하고 가능한 모든 방법에서 훨씬 쉽습니다 . 컬렉션의 중첩 된 컬렉션이있는 경우 최상위 수준 개체와 Load해당 하위 개체를 반복해야 할 수도 있습니다. 손에서 벗어날 수 있습니다.
빠른 경험 법칙
시도 하지 않도록 어떤 가진 개 이상의 Include통화를 단일 쿼리를. 나는 EF의 쿼리가 그 이상을 인식하기에는 너무 추악하다는 것을 발견했습니다. 또한 SQL Server 쿼리에 대한 경험 규칙과 일치합니다. 단일 쿼리에서 최대 4 개의 JOIN 문이 매우 잘 작동하지만 그 후에는 리팩토링 을 고려할 때 입니다.
그러나이 모든 것은 시작에 불과합니다.
스키마, 환경, 데이터 및 기타 여러 요인 에 따라 다릅니다 .
결국 각 방식으로 시도해 보시기 바랍니다 .
사용할 합리적인 "기본"패턴을 선택하고, 충분히 좋은지 확인하고, 그렇지 않은 경우 취향에 맞게 최적화하십시오.
Include()SQL에 다음과 같이 기록됩니다 JOIN. 데이터베이스 왕복 1 회.
각 Load()명령어는 요청 된 엔터티를 "명시 적으로로드"하므로 호출 당 하나의 데이터베이스 왕복입니다.
따라서이 Include()경우 가장 현명한 선택이 될 수 있지만 데이터베이스 레이아웃,이 코드가 호출되는 빈도 및 DbContext수명에 따라 다릅니다 . 두 가지 방법을 모두 시도하고 쿼리를 프로파일 링하고 타이밍을 비교하는 것은 어떻습니까?
관련 엔티티로드를 참조하십시오 .
나는 그의 대답 에서 @MichaelEdenfield에 동의 하지만 중첩 컬렉션 시나리오에 대해 의견을 말하고 싶었습니다. 쿼리를 뒤집어서 중첩 루프 (및 데이터베이스에 대한 많은 결과 호출)를 수행해야하는 상황을 피할 수 있습니다.
고객의 주문 컬렉션을 반복 한 다음 주문의 주문 항목 컬렉션을 통해 또 다른 중첩 루프를 수행하는 대신 다음과 같은 필터를 사용하여 주문 항목을 직접 쿼리 할 수 있습니다.
context.OrderItems.Where(x => x.Order.CustomerId == customerId);
중첩 루프 내에서로드와 동일한 결과 데이터를 얻을 수 있지만 데이터베이스에 대한 단일 호출 만 있으면됩니다.
또한 Includes에서 고려해야 할 특별한 경우가 있습니다. 부모와 자식 간의 관계가 일대일 인 경우 부모 데이터가 여러 번 반환되는 문제는 문제가되지 않습니다.
대다수의 경우 자녀가 존재하지 않는 경우 어떤 영향을 미칠지 잘 모르겠습니다. 일대일 관계의 희소 자식은 위에서 설명한 직접 쿼리 기술에 더 적합 할 수 있습니다.
Include 은 쿼리중인 엔티티뿐만 아니라 모든 관련 엔티티를로드 할 때 즉시로드의 예입니다.
Load의 수동 재정의입니다 EnableLazyLoading. 이 설정이 false. 요청한 엔티티를 여전히 느리게로드 할 수 있습니다..Load()
Eager, Explicit 또는 Lazy Loading을 사용할지 항상 결정하기가 어렵습니다.
어쨌든 내가 권장하는 것은 항상 프로파일 링을 수행하는 것입니다. 이것이 귀하의 요청이 수행되는지 여부를 확인하는 유일한 방법입니다.
도움이되는 도구가 많이 있습니다. 프로파일 링을 수행하는 여러 가지 방법을 나열한 Julie Lerman의이 기사를 살펴보십시오 . 한 가지 간단한 해결책은 SQL Server Management Studio에서 프로파일 링 을 시작 하는 것 입니다.
실행 계획을 이해하는 데 도움이 될 DBA (근처에있는 경우)와상의하는 것을 주저하지 마십시오. 데이터로드 및 성능에 대한 섹션을 작성한 이 프레젠테이션을
볼 수도 있습니다 .
One more thing to add to this thread. It depends on what server you use. If you are working on sql server it's ok to use eager loading but for sqlite you will have to use .Load() to avoid crossloading exception cause sqlite can not deal with some include statements that go deeper than one dependency level
참고URL : https://stackoverflow.com/questions/19319116/include-vs-load-performance-in-entityframework
'Program Club' 카테고리의 다른 글
| 새 선택적 매개 변수를 허용하도록 SQL 서버 함수 변경 (0) | 2020.11.30 |
|---|---|
| Twitter Bootstrap 캐 러셀 높이가 다른 이미지로 인해 화살표가 튀는 현상 (0) | 2020.11.30 |
| 개체 'Users', 데이터베이스 'XXX', 스키마 'dbo'에 대한 SELECT 권한이 거부되었습니다. (0) | 2020.11.30 |
| Android 스튜디오로 프로젝트를 빌드하지 못했습니다. (0) | 2020.11.30 |
| 'data-sort'속성에 따라 jQuery에서 div를 정렬합니까? (0) | 2020.11.30 |