Entity Framework가 너무 느립니다. 내 옵션은 무엇입니까? [닫은]


93

"Do n't Optimize Prematurely"만트라를 따르고 Entity Framework를 사용하여 WCF 서비스를 코딩했습니다.

그러나 성능을 프로파일 링했으며 Entity Framework가 너무 느립니다. (내 앱은 약 1.2 초 만에 2 개의 메시지를 처리하는데, 다시 작성중인 (레거시) 앱은 동시에 5-6 개의 메시지를 처리합니다. (레거시 앱은 DB 액세스를 위해 sprocs를 호출합니다.)

내 프로파일 링은 Entity Framework가 메시지 당 많은 시간을 차지한다는 것을 가리 킵니다.

그래서 내 옵션은 무엇입니까?

  • 더 나은 ORM이 있습니까?
    (일반적인 객체 읽기 및 쓰기를 지원하고 빠르게 수행하는 것 ..)

  • Entity Framework를 더 빠르게 만드는 방법이 있습니까?
    ( 참고 : 내가 더 빨리 말한다는 것은 첫 번째 통화가 아니라 장기를 의미합니다. 메시지.)

  • 서비스 속도를 높이는 데 도움이되는 신비한 세 번째 옵션입니다.

참고 : 대부분의 DB 상호 작용은 생성 및 업데이트입니다. 나는 선택과 삭제를 거의하지 않습니다.


이것은 'linq is slow'의 재해시처럼 들리는데, 그것이 EF인지 어떻게 알 수 있습니까? 모든 변경 사항을 프로파일 링했습니까?
Maess

6
일부 답변은 쿼리를 가리키고 있습니다. 내 경험상 EF의 속도 저하는 쿼리와 거의 관련이 없지만 대신 구체화 비용과 관련이 있으며 이러한 비용은 종종 변경 추적 및 생성 된 인스턴스에 미치는 영향과 관련이 있습니다. 불행히도 저는 당신을위한 은색 총알이 없기 때문에 이것은 단지 코멘트 일뿐입니다. 그러나 프로파일 링이 높은 물질화 비용을 드러내는 지 확인하고 만약 그렇다면 상기 비용에 대해 무엇을 할 수 있는지 조사하는 것이 좋습니다.
Anthony Pegram 2011-12-01

@Maess-프로파일 링을했고 느린 EF / DB라는 것을 알았다고 생각했습니다. 어느 쪽이든 맞습니다. 나는 그것을 프로파일 링했으며 주요 원인은 EF / DB 상호 작용입니다.
Vaccano

@Anthony-구체화가 먼저 실행되는 것이 아닌가? 그렇다면 매우 느리다는 것이 맞습니다. 첫 번째 실행은 매우 느립니다. 그러나 내가 지적했듯이 나는 그것에 대해 너무 걱정하지 않습니다. 문제는 총 처리량입니다. (그것이 Materialization이 아니라면 내 문제의 원인인지 확인하기 위해 조사가 필요합니다)
Vaccano

1
@Vaccano, 아니요, 구체화는 데이터베이스에서 데이터를 가져와 해당 데이터를 나타내는 개체의 그래프를 인스턴스화하고 채우는 프로세스입니다. 코드가 jitted (또는 Sql Server가 쿼리 실행 계획을 생성 할 수도 있음)에 따른 첫 실행 성능에 대해 말하는 것이 아니라 개체 형태로 데이터를 가져올 때마다 발생하는 일입니다.
Anthony Pegram 2011

답변:


45

Entity Framework에서 실제로 실행 한 SQL 명령을 프로파일 링하여 시작해야합니다. 구성 (POCO, 자체 추적 엔터티)에 따라 최적화 할 여지가 많습니다. ObjectSet<T>.ToTraceString()메서드를 사용하여 SQL 명령 (디버그 모드와 릴리스 모드간에 다르지 않아야 함)을 디버깅 할 수 있습니다 . 추가 최적화가 필요한 쿼리가 발생하면 몇 가지 프로젝션을 사용하여 수행하려는 작업에 대한 자세한 정보를 EF에 제공 할 수 있습니다.

예:

Product product = db.Products.SingleOrDefault(p => p.Id == 10);
// executes SELECT * FROM Products WHERE Id = 10

ProductDto dto = new ProductDto();
foreach (Category category in product.Categories)
// executes SELECT * FROM Categories WHERE ProductId = 10
{
    dto.Categories.Add(new CategoryDto { Name = category.Name });
}

다음으로 대체 될 수 있습니다.

var query = from p in db.Products
            where p.Id == 10
            select new
            {
                p.Name,
                Categories = from c in p.Categories select c.Name
            };
ProductDto dto = new ProductDto();
foreach (var categoryName in query.Single().Categories)
// Executes SELECT p.Id, c.Name FROM Products as p, Categories as c WHERE p.Id = 10 AND p.Id = c.ProductId
{
    dto.Categories.Add(new CategoryDto { Name = categoryName });
}

방금 머릿속에서 입력 했으므로 이것이 정확히 실행되는 방법은 아니지만 쿼리에 대해 아는 모든 것을 말하면 EF가 실제로 몇 가지 멋진 최적화를 수행합니다 (이 경우에는 범주가 필요함). 이름). 그러나 이는 예상로드 (db.Products.Include ( "Categories"))와는 다릅니다. 프로젝션은로드 할 데이터의 양을 더 줄일 수 있기 때문입니다.


40
이 응답은 익명 형식이 정의 된 메서드 외부에서 액세스 할 수 없다는 사실을 깨닫기 전까지는 합리적으로 들립니다. 복잡한 객체를로드하고 메가 모스를 쓰지 않으려면 새로운 익명 유형을 일종의 POCO로 역 직렬화해야합니다. 다시 말하지만, 그렇게함으로써 본질적으로 자신의 엔티티 프레임 워크를 다시 작성했음을 깨닫기 전까지는 거의 합리적으로 들립니다. 말도 안돼.
Doug

5
이로 인해 속도가 15x-20x 증가했습니다.
Dave Cousineau

12
흥미롭고 도움이되는 답장, 꽤 오랜 시간이 지난 후에도 여전히 유효합니다. @Doug : 정말 헛소리가 아니에요. 정말 필요로하는 몇 가지 쿼리 만 최적화 (프로젝션 사용)하기 때문입니다. EF와 POCO는 합리적인 기본값을 제공합니다.
Victor

2
@Doug 대부분의 응용 프로그램에는보기 전용 시나리오에 대한보기 모델이 있습니다. 데이터를 가져 오는 것만 큼 많은 매핑을 수행 할 수 있습니다.
Casey

4
나는 ORM이 미래라고 생각하기 위해 사용합니다. 내가 그들을 사용하기 시작할 때까지 그들은 단지 의미가 있습니다. 그런 다음 Dapper를 찾았습니다 . 이제 이와 같은 솔루션을 볼 때 복잡성이 어떻게 빠르게 증가하는지에 대해 겁이납니다. 추상화 된 SQL을 C #으로 작성하는 것은 삶을 살아갈 방법이 아닙니다.
Michael Silver

80

문제는 Entity Framework와 같은 제품이 훨씬 더 많은 코드를 실행하기 때문에 항상 느리고 비효율적이라는 것입니다.

또한 사람들이 LINQ 쿼리를 최적화하고, 생성 된 SQL을보고, 디버거를 사용하고, 사전 컴파일하고, 많은 추가 단계를 수행해야한다고 제안하는 것은 어리석은 일입니다. 즉, 많은 시간을 낭비합니다. 아무도 말하지 않습니다-단순화하십시오! 모두는 더 많은 단계를 밟아 (시간 낭비) 일을 더 복잡하게 만들고 싶어합니다.

상식적인 접근 방식은 EF 또는 LINQ를 전혀 사용하지 않는 것입니다. 일반 SQL을 사용하십시오. 그것은 잘못된 것이 아닙니다. 프로그래머들 사이에 무리의 사고 방식이 있고 거기에있는 모든 신제품을 사용하려는 충동을 느낀다고해서 그것이 좋다거나 작동 할 것이라는 의미는 아닙니다. 대부분의 프로그래머는 대기업에서 발표 한 모든 새로운 코드를 통합하면 더 똑똑한 프로그래머가된다고 생각합니다. 전혀 사실이 아닙니다. 스마트 프로그래밍은 대부분의 경우 두통과 불확실성을 줄이고 최소한의 시간에 더 많은 작업을 수행하는 방법에 관한 것입니다. 기억하십시오-시간! 이것이 가장 중요한 요소이므로 단순히 '패턴'이라고 불리는 이상한 일부를 따르기 위해 작성된 불량 / 비대해진 코드로 문제를 해결하는 데 낭비하지 않는 방법을 찾으십시오.

휴식을 취하고, 삶을 즐기고, 코딩에서 휴식을 취하고, 추가 기능, 코드, 제품, '패턴'사용을 중단하십시오. 인생은 짧고 코드의 수명은 더 짧으며 확실히 로켓 과학이 아닙니다. LINQ, EF 등의 계층을 제거하면 코드가 효율적으로 실행되고 확장되며 유지 관리가 쉽습니다. 너무 많은 추상화는 나쁜 '패턴'입니다.

그리고 그것이 당신의 문제에 대한 해결책입니다.


156
이것은 아기를 목욕물로 내 던지는 것입니다. 병목 현상을 최적화합니다. EF는 몇 군데에서는 너무 느리지 만 다른 곳에서는 충분히 빠르기 때문에 어리석은 일입니다. 둘 다 사용하지 않는 이유는 무엇입니까? EF는 저장 프로 시저와 원시 SQL을 잘 처리합니다. 방금 10 초 이상 걸리는 LINQ-to-SQL 쿼리를 ~ 1 초가 걸리는 SP로 변환했지만 모든 LINQ-to-SQL을 버리지는 않을 것입니다. 더 적은 코드와 더 적은 오류 공간으로 다른 간단한 경우에 많은 시간을 절약했으며 쿼리는 컴파일러가 확인되고 데이터베이스와 일치합니다. 코드가 적을수록 유지 관리가 쉽고 오류가 발생할 여지가 적습니다.
JulianR

12
전반적으로 귀하의 조언은 좋지만 EF 또는 기타 추상화가 10 %의 시간 동안 잘 작동하지 않기 때문에 포기하는 것은 옳지 않다고 생각합니다.
JulianR

50
일반 SQL = 유지하기 쉬움? 비즈니스 로직이 많은 매우 큰 앱에는 해당되지 않습니다. 재사용 가능한 복잡한 SQL을 작성하는 것은 쉬운 일이 아닙니다. 개인적으로 나는 EF에 몇 가지 성능 문제가 있었지만 이러한 문제는 RAD 및 DRY 유지 측면에서 적절한 ORM의 이점과 비교되지 않습니다 (복잡도가 관련된 경우).
MemeDeveloper 2012 년

13
+ 10 ^ 100 너무 많은 추상화는 나쁜 '패턴'입니다
Makach

58
-1. "EF는 항상 느리고 비효율적입니다." 나는 당신이 왜 이런 것을 절대적인 진실이라고 주장하는지 모르겠습니다. 더 많은 계층을 거치면 속도가 느려지지만 그 차이가 눈에 띄는지는 데이터 양과 실행되는 쿼리 유형과 같은 상황에 따라 완전히 달라집니다. 나에게 이것은 C ++보다 더 높은 추상화이기 때문에 'C #은 항상 느리고 비효율적 일 것이다'라고 말하는 것과 동일합니다. 그러나 많은 사람들은 생산성이 무게 성능 손실 (있을 경우)보다 훨씬 더 많이 증가하기 때문에 사용하기로 선택합니다. 동일은 EF 적용
Despertar

37

한 가지 제안은 단일 레코드 CRUD 문에만 LINQ to Entity Framework를 사용하는 것입니다.

더 많은 관련 쿼리, 검색,보고 등의 경우 저장 프로 시저를 작성하고 MSDN에 설명 대로 Entity Framework 모델에 추가합니다 .

이것은 몇 개의 내 사이트에서 취한 접근 방식이며 생산성과 성능 사이에서 좋은 절충안 인 것 같습니다. Entity Framework는 당면한 작업에 대해 항상 가장 효율적인 SQL을 생성하지는 않습니다. 이유를 파악하는 데 시간을 소비하는 대신 더 복잡한 쿼리에 대한 저장 프로 시저를 작성하면 실제로 시간을 절약 할 수 있습니다. 프로세스에 익숙해지면 저장된 프로 시저를 EF 모델에 추가하는 것이 너무 번거롭지 않습니다. 물론이를 모델에 추가 할 때 얻을 수있는 이점은 ORM을 사용하여 강력한 유형의 장점을 모두 얻을 수 있다는 것입니다.


db.athlete.find (id) 등과 같은 스캐 폴딩에 사용되는 방법에 대한 아이디어가 있습니까? ADO.NET 또는 dapper와 비교하여 어떻게 수행합니까 ??
그것은 함정

15

순수하게 데이터를 가져 오는 경우 EF가 가져 오는 항목을 추적하지 않도록 지시하면 성능에 큰 도움이됩니다. MergeOption.NoTracking을 사용하여이 작업을 수행하십시오. EF는 쿼리를 생성하고, 실행하고, 결과를 개체로 역 직렬화 할뿐, 엔터티 변경 사항이나 그 특성을 추적하지 않습니다. 쿼리가 단순하다면 (데이터베이스가 반환 될 때까지 많은 시간을 소비하지 않음) NoTracking으로 설정하면 쿼리 성능이 두 배가 될 수 있음을 발견했습니다.

MergeOption 열거 형에 대한 MSDN 문서를 참조하십시오.

ID 확인, 상태 관리 및 변경 추적

이것은 EF 성능에 대한 좋은 기사 인 것 같습니다.

성능 및 Entity Framework


9
누구든지이 작업을하기 전에 여기에서 읽어 보는 것이 좋습니다. stackoverflow.com/questions/9259480/…
leen3o

6

애플리케이션을 프로파일 링했다고 말합니다. ORM도 프로파일 링했습니까? EF 코드를 최적화 할 수있는 부분을 강조하는 Ayende의 EF 프로파일 러가 있습니다. 여기에서 찾을 수 있습니다.

http://efprof.com/

성능을 확보해야하는 경우 ORM과 함께 기존 SQL 접근 방식을 사용할 수 있습니다.

더 빠르고 더 나은 ORM이 있다면? 객체 / 데이터 모델에 따라 Dapper , Massive 또는 PetaPoco 와 같은 마이크로 ORM 중 하나를 사용하는 것을 고려할 수 있습니다.

Dapper 사이트는 다른 ORM과 비교하는 방법에 대한 아이디어를 제공하는 몇 가지 비교 벤치 마크를 게시합니다. 그러나 마이크로 ORM이 EF 및 NH와 같은 전체 ORM의 풍부한 기능 세트를 지원하지 않는다는 점은 주목할 가치가 있습니다.

RavenDB를 살펴볼 수 있습니다 . 이것은 매핑이 필요 없이 POCO를 직접 저장할 수있는 비 관계형 데이터베이스 (Ayende에서 다시 제공)입니다 . RavenDB는 읽기에 최적화되어 있으며 스키마를 조작하고 객체를 해당 스키마에 매핑 할 필요가 없으므로 개발자의 삶을 훨씬 더 쉽게 만듭니다. 그러나 이것은 ORM 접근 방식을 사용하는 것과는 상당히 다른 접근 방식이며 제품 사이트에 설명되어 있습니다 .


4

@Slauma의 답변은 여기 에서 속도를 높이는 데 매우 유용합니다. 나는 삽입과 업데이트 모두에 동일한 종류의 패턴을 사용했고 성능이 급등했습니다.


2

내 경험상 EF가 아니라 ORM 자체의 문제입니다.

일반적으로 모든 ORM은 최적화 된 쿼리가 아닌 N + 1 문제로 고통받습니다 . 내 최선의 추측은 성능 저하를 유발하는 쿼리를 추적하고 ORM 도구를 조정하거나 SPROC로 해당 부분을 다시 작성하는 것입니다.


2
사람들은 계속 이렇게 말합니다. 그러나 구식 ADO를 사용하여 간단한 select 문을 설정하고 EF 컨텍스트와 EF를 사용하는 동일한 간단한 선택은 항상 상당히 느립니다. 나는 EF를 정말 좋아하고 싶지만, 삶을 더 쉽게 만드는 대신 계속 힘들게 만듭니다.
Sinaesthetic 2014-06-22

1
@Sinaesthetic 물론 느립니다. 마찬가지로 Linq to Objects를 사용하여 작성된 코드는 일반적으로 그렇지 않은 코드보다 느립니다. 문제는 실제로 그것이 더 빠르거나 빠른지 (어떻게 할 수 있었는지, 수작업으로 발행 한 쿼리를 여전히 발행해야 할 때 어떻게 될 수 있습니까?)가 아니라 1) 여전히 귀하의 요구에 충분히 빠른지 2) 저장합니다 코드 작성 시간 3) 이점이 비용을 상쇄합니다. 이러한 항목을 바탕으로 EF는 많은 프로젝트에 적합하다고 생각합니다.
Casey

@Sinaesthetic 또한 ORM을 사용하지 않으면 각 SQL 쿼리가 미세 조정되고 최적화되는 것이 아니라 응용 프로그램이 사내, 유기적, 열악한 개발로 끝나는 것이 아닙니다. -당신의 팀이 예외적으로 훈련되고 성과에 대해 매우 염려하지 않는 한, 지원이 잘되지 않는 ORM.
Casey


1

이 문제도 만났습니다. 너무 잘 작동하기 때문에 EF에 덤프하는 것이 싫지만 느립니다. 대부분의 경우 레코드를 찾거나 업데이트 / 삽입하고 싶습니다. 이와 같은 간단한 작업조차도 느립니다. 테이블에서 1100 개의 레코드를 목록으로 되 돌렸고이 작업은 EF에서 6 초가 걸렸습니다. 저에게 이것은 너무 길고 저축조차 너무 오래 걸립니다.

나는 결국 나만의 ORM을 만들었습니다. 데이터베이스에서 동일한 1100 개의 레코드를 가져 왔고 ORM은 EF보다 훨씬 빠른 2 초가 걸렸습니다. 내 ORM의 모든 것이 거의 즉각적입니다. 현재 유일한 제한은 MS SQL Server에서만 작동하지만 Oracle과 같은 다른 서버에서도 작동하도록 변경할 수 있다는 것입니다. 나는 지금 모든 것에 MS SQL Server를 사용합니다.

내 ORM을 시도하고 싶다면 여기 링크와 웹 사이트가 있습니다 :

https://github.com/jdemeuse1204/OR-M-Data-Entities

또는 너깃을 사용하려는 경우 :

PM> 설치 패키지 OR-M_DataEntities

문서도 거기에 있습니다


0

프로파일 링 한 후에 만 ​​최적화하는 것이 합리적입니다. DB 액세스가 느리다는 것을 알게되면 저장 프로 시저 사용으로 변환하고 EF를 유지할 수 있습니다. 느린 것이 EF 자체라는 것을 알게되면 다른 ORM으로 전환하거나 ORM을 전혀 사용하지 않아야 할 수 있습니다.


0

초당 120 개의 요청을 쉽게 수행하는 유사한 응용 프로그램 (Wcf-> EF-> 데이터베이스)이 있으므로 EF가 여기서 문제가되지 않는다고 확신합니다. 즉, 컴파일 된 쿼리로 성능이 크게 향상되었습니다.


내 코드의 98 %는 Create and Update 호출입니다. 그것이 차이가 나는지는 모르겠지만 초당 120보다 훨씬 느립니다.
Vaccano

예, 그것은 일반적인 응용 프로그램이 아닙니다. 응용 프로그램을 프로파일 링하는 것이 좋습니다. 우리는 주로 ... 읽기
NP-하드

0

나는 EF, LINQ to SQL 및 dapper를 사용했습니다. Dapper가 가장 빠릅니다. 예 : 각각 4 개의 하위 레코드가있는 1000 개의 메인 레코드가 필요했습니다. LINQ to sql을 사용했는데 약 6 초가 걸렸습니다. 그런 다음 dapper로 전환하여 단일 저장 프로 시저에서 2 개의 레코드 세트를 검색하고 각 레코드에 대해 하위 레코드를 추가했습니다. 총 시간은 1 초입니다.

또한 저장 프로시 저는 교차 적용과 함께 테이블 값 함수를 사용했으며 스칼라 값 함수가 매우 느리다는 것을 발견했습니다.

내 조언은 EF 또는 LINQ to SQL을 사용하고 특정 상황에서는 멋지게 전환하는 것입니다.


-1

Entity Framework는 자체적으로 주요 병목 현상을 일으키지 않아야합니다. 다른 원인이있을 가능성이 있습니다. EF를 Linq2SQL로 전환 할 수 있습니다. 둘 다 비교 기능이 있고 코드를 쉽게 변환 할 수 있어야하지만 대부분의 경우 Linq2SQL이 EF보다 빠릅니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.