2010-07-28 44 views
0

我有一个L2S查询有几个连接,它应该在大约3秒内返回11条记录。但是,除非我指定Take参数(即使它只返回11条记录,我仍使用Take(20)),但在30秒后它会超时,在这种情况下,它将返回3个预期时间范围内的11条记录。为什么此查询超时?

查询看起来是这样的:

(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) 

现在,真正离奇的是,如果我执行一个SQL Management Studio中,它会在3秒内返回11行,但生成它的linq查询将在30秒的活动后超时。

指定Take参数没有多大意义。我碰到一些错误?

注意:代码超时没有Take()参数,无论我是从我的应用程序还是Linqpad执行它。同样,在应用程序和linqpad中,它都可以正常使用Take()参数。而且,如果没有区别,它只会返回19行。

回答

1

比较带和不带.Take(top n)的查询的执行计划。您可能第一次为查询执行了一个错误的执行计划,并且添加Take只是更改了查询,以便再次编译。

用sp_recompile或dbcc freeproccache删除执行计划,看看是否有所作为。

您还可以使用a profiler提取有关查询费用,执行计划等详细信息...

+0

我不知道我的理解。如果我执行由L2S查询生成的SQL,则没有问题。生成的SQL的执行计划不应该与L2S查询相同吗? – 2010-07-28 07:51:08

+0

Linq-to-SQL查询已转换为SQL。如果超时,那么它被翻译的特定TSQL可能被高速缓存在执行计划缓存中,但执行计划不甚理想。 sp_recompile,或者dbcc freeproccache会强制一个新的执行计划... – KristoferA 2010-07-28 07:54:10

+0

...哦,并且使用一个分析器,您可以获得L2S正在使用的确切SQL查询。在你的问题中,从“声明”语句开始的并不是L2S打击数据库的原因。 L2S将使用sp_executesql来运行它,以确保它在存储的proc计划缓存中结束... – KristoferA 2010-07-28 07:56:24