2010-07-28 2 views
0

약 3 초 안에 11 개의 레코드를 반환해야하는 여러 조인이있는 L2S 쿼리가 있습니다. 그러나 Take 매개 변수를 지정하지 않으면 (11 레코드 만 반환하더라도 Take (20)을 사용함) 30 초 후에 시간이 초과됩니다.이 경우 11 개의 레코드로 3 초의 예상 시간 프레임에 반환됩니다.왜이 쿼리가 시간 초과됩니까?

쿼리는 다음과 같습니다

(from q in TransmittalDetails where q.TransmittalHeader.TransmittalEntityID == 196 
     && q.TransmittalHeader.DateRangeBeginTimeID == 20100101 
     && q.TransmittalHeader.ScenarioID == 2 
     && q.LineItem.AccountType.AccountCategory.AccountGroup. 
      AccountSummary.AccountSummaryID == 6 
select new { 
q.LineItem.AccountType.AccountCategory.AccountGroup.AccountGroupID, 
q.LineItem.AccountType.AccountCategory.AccountGroup.AccountGroup1 
    }).Distinct() 

이이처럼 보이는 몇 가지 SQL을 생성합니다

DECLARE @p0 Int = 196 
DECLARE @p1 Int = 20100101 
DECLARE @p2 Int = 2 
DECLARE @p3 Int = 6 

SELECT DISTINCT [t5].[AccountGroupID], [t5].[AccountGroup] AS [AccountGroup1] 
FROM [dbo].[TransmittalDetail] AS [t0] 
INNER JOIN [dbo].[TransmittalHeader] AS [t1] ON [t1].[TransmittalHeaderID] = 
    [t0].[TransmittalHeaderID] 
INNER JOIN [dbo].[LineItem] AS [t2] ON [t2].[LineItemID] = [t0].[LineItemID] 
LEFT OUTER JOIN [dbo].[AccountType] AS [t3] ON [t3].[AccountTypeID] = 
    [t2].[AccountTypeID] 
LEFT OUTER JOIN [dbo].[AccountCategory] AS [t4] ON [t4].[AccountCategoryID] = 
    [t3].[AccountCategoryID] 
LEFT OUTER JOIN [dbo].[AccountGroup] AS [t5] ON [t5].[AccountGroupID] = 
    [t4].[AccountGroupID] 
LEFT OUTER JOIN [dbo].[AccountSummary] AS [t6] ON [t6].[AccountSummaryID] = 
    [t5].[AccountSummaryID] 
WHERE ([t1].[TransmittalEntityID] = @p0) AND ([t1].[DateRangeBeginTimeID] = @p1) 
    AND ([t1].[ScenarioID] = @p2) AND ([t6].[AccountSummaryID] = @p3) 

이제, 정말 이상한 부분입니다 내가 실행하면 그 관리 Studio에서 SQL, 그것은 3 초에 11 개의 행을 반환하지만, 그것을 생성하는 linq 쿼리는 30 초 활동 후에 시간 초과됩니다.

Take 매개 변수를 지정하는 것은 의미가 없습니다. 내가 어떤 벌레를 치는거야?

참고 : 코드가 Take() 매개 변수없이 응용 프로그램 또는 Linqpad에서 실행되는지 여부에 관계없이 시간이 만료됩니다. 마찬가지로, app 및 linqpad에서 Take() 매개 변수를 사용하면 문제가 없습니다. 또한 별개 기호가 없으면 19 행만 반환합니다.

답변

1

.Take (top n)가있는 쿼리와없는 쿼리의 실행 계획을 비교하십시오. 처음에는 쿼리에 대한 잘못된 실행 계획이 있고 아마도 Take를 추가하면 쿼리가 다시 컴파일되도록 변경되었습니다.

sp_recompile 또는 dbcc freeproccache를 사용하여 실행 계획을 삭제하고 차이가 있는지 확인하십시오. 또한 쿼리 비용, 실행 계획 등에 대한 자세한 정보를 추출하는 a profiler을 사용할 수 있습니다

...

+0

나는 이해가 확실하지 않다. L2S 쿼리에 의해 생성 된 SQL을 실행해도 아무런 문제가 없습니다. 생성 된 SQL의 실행 계획이 L2S 쿼리와 동일하지 않아야합니까? –

+0

Linq-to-SQL 쿼리가 SQL로 변환됩니다. 시간이 초과되면 변환 된 특정 TSQL이 최적의 실행 계획보다 적게 실행 계획 캐시에 캐시됩니다. 관련된 테이블 중 하나에 sp_recompile 또는 dbcc freeproccache가 새로운 실행 계획을 강제합니다 ... – KristoferA

+0

... 아, 프로파일 러를 사용하면 L2S가 데이터베이스를 치는 정확한 SQL 쿼리를 얻을 수 있습니다. 귀하의 질문에 "선언"진술로 시작하는 것은 L2S가 DB를 치는 것이 아닙니다. L2S는 sp_executesql을 사용하여 저장된 proc 계획 캐시에서 끝나기 위해 실행합니다. – KristoferA

관련 문제