programing

Entity Framework 쿼리는 느리지 만 SqlQuery의 동일한 SQL은 빠름

nasanasas 2020. 10. 10. 10:09
반응형

Entity Framework 쿼리는 느리지 만 SqlQuery의 동일한 SQL은 빠름


.NET Framework 버전 4에서 Entity Framework Code-First를 사용하는 매우 간단한 쿼리와 관련된 정말 이상한 성능이 표시됩니다. LINQ2Entities 쿼리는 다음과 같습니다.

 context.MyTables.Where(m => m.SomeStringProp == stringVar);

실행하는 데 3000 밀리 초 이상이 걸립니다. 생성 된 SQL은 매우 간단합니다.

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = '1234567890'

이 쿼리는 Management Studio를 통해 실행될 때 거의 즉시 실행됩니다. SqlQuery 함수를 사용하도록 C # 코드를 변경하면 5-10 밀리 초 안에 실행됩니다.

 context.MyTables.SqlQuery("SELECT [Extent1].[ID] ... WHERE [Extent1].[SomeStringProp] = @param", stringVar);

따라서 정확히 동일한 SQL, 결과 엔터티는 두 경우 모두 변경 추적되지만 둘 사이의 성능 차이는 크게 다릅니다. 무엇을 제공합니까?


그것을 발견. SQL 데이터 유형의 문제로 밝혀졌습니다. SomeStringProp데이터베이스 열은 varchar 이었지만 EF는 .NET 문자열 유형이 nvarchar라고 가정합니다. 쿼리 중에 DB가 비교를 수행하는 결과 번역 프로세스는 시간이 오래 걸립니다. 나는 EF Prof가 나를 타락하게 이끌었다 고 생각합니다. 실행되는 쿼리의 더 정확한 표현은 다음과 같습니다.

 SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
 ...
 FROM [MyTable] as [Extent1]
 WHERE [Extent1].[SomeStringProp] = N'1234567890'

따라서 결과 수정은 올바른 SQL 데이터 유형을 나타내는 코드 우선 모델에 주석을 추가하는 것입니다.

public class MyTable
{
    ...

    [Column(TypeName="varchar")]
    public string SomeStringProp { get; set; }

    ...
}

EF에서 만든 쿼리 속도를 늦추는 이유는 nullable이 아닌 스칼라와 nullable 스칼라를 비교하는 것입니다.

long? userId = 10; // nullable scalar

db.Table<Document>().Where(x => x.User.Id == userId).ToList() // or userId.Value
                                ^^^^^^^^^    ^^^^^^
                                Type: long   Type: long?

이 쿼리에는 35 초가 걸렸습니다. 그러나 다음과 같은 작은 리팩토링 :

long? userId = 10;
long userIdValue = userId.Value; // I've done that only for the presentation pursposes

db.Table<Document>().Where(x => x.User.Id == userIdValue).ToList()
                                ^^^^^^^^^    ^^^^^^^^^^^
                                Type: long   Type: long

놀라운 결과를 제공합니다. 완료하는 데 50ms 밖에 걸리지 않았습니다. EF의 버그 일 가능성이 있습니다.


유창한 매핑을 사용하는 경우 IsUnicode(false)구성의 일부로 사용 하여 동일한 효과를 얻을 수 있습니다.

http://msdn.microsoft.com/en-us/data/jj591617.aspx#1.9

http://msdn.microsoft.com/en-us/library/gg696416%28v=vs.103%29.aspx


나는 같은 문제가 있었지만 (SQL 관리자에서 실행할 때 쿼리가 빠르다) EF에서 실행하면 시간 초과가 만료됩니다.

보기에서 생성 된 엔티티에 잘못된 엔티티 키가있는 것으로 밝혀졌습니다. 따라서 엔터티에는 동일한 키가있는 중복 행이 있으며 배경에서 그룹화를 수행해야했습니다.


나는 또한 복잡한 ef 쿼리로 이것을 발견했습니다. 6 초 ef 쿼리를 생성 한 서브 초 SQL 쿼리로 줄인 저에게 한 가지 수정 사항은 지연로드를 끄는 것입니다.

이 설정 (ef 6)을 찾으려면 .edmx 파일로 이동하여 속성-> 코드 생성-> 지연로드 활성화를 확인하십시오. false로 설정하십시오.

저에게 성능이 크게 향상되었습니다.


나도이 문제가 있었다. 제 경우의 범인은 SQL-Server 매개 변수 스니핑 이었습니다.

내 문제가 실제로 매개 변수 스니핑 때문이라는 첫 번째 단서는 "set arithabort off"또는 "set arithabort on"을 사용하여 쿼리를 실행하면 Management Studio에서 실행 시간이 크게 달라진다는 것입니다. ADO.NET은 기본적으로 "set arithabort off"를 사용하고 Management Studio는 기본적으로 "set arithabort on"을 사용하기 때문입니다. 쿼리 계획 캐시는이 매개 변수에 따라 다른 계획을 유지합니다.

I disabled query plan caching for the query, with the solution you can find here.


You can use the following tricks to fasten your queries -

  1. Set ctx.Configuration.ProxyCreationEnabled to false right before you get the context.
  2. Also, .Select(c => new {c.someproperty}) will fetch only the required data and not the whole bunch.

Let me know if this helped.

참고URL : https://stackoverflow.com/questions/15767803/entity-framework-query-slow-but-same-sql-in-sqlquery-is-fast

반응형