Linq to sql 为什么查询超时?

Linq to sql 为什么查询超时?,linq-to-sql,performance,Linq To Sql,Performance,我有一个L2S查询,有几个连接,应该在大约3秒钟内返回11条记录。但是,它会在30秒后超时,除非我指定一个Take参数(我使用了Take(20),即使它只返回11条记录),在这种情况下,它会在预期的3秒时间范围内返回11条记录 查询如下所示: (from q in TransmittalDetails where q.TransmittalHeader.TransmittalEntityID == 196 && q.TransmittalHeader.DateRang

我有一个L2S查询,有几个连接,应该在大约3秒钟内返回11条记录。但是,它会在30秒后超时,除非我指定一个Take参数(我使用了Take(20),即使它只返回11条记录),在这种情况下,它会在预期的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()
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:

(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()
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)
现在,真正奇怪的是,如果我在ManagementStudio中执行SQL,它会在3秒内返回11行,但生成它的linq查询将在30秒后超时

指定Take参数没有多大意义。我是不是碰到什么虫子了


注意:无论是从我的应用程序还是从Linqpad执行,代码都会在没有Take()参数的情况下超时。同样,在app和linqpad中,使用Take()参数也可以正常工作。另外,如果没有distinct,它只返回19行。

比较查询的执行计划是否有.Take(顶部n)。您可能第一次得到的查询执行计划不正确,添加Take只是更改了查询,因此再次编译它

使用sp_recompile或dbcc freeproccache删除执行计划,看看这是否会产生影响


您还可以使用提取有关查询成本、执行计划等的更多信息

我不太明白。如果执行L2S查询生成的SQL,则没有问题。生成的SQL的执行计划不应该与L2S查询相同吗?Linq to SQL查询被转换为SQL。如果它超时,则转换为的特定TSQL可能会以低于最佳执行计划的方式缓存在执行计划缓存中。sp_在其中一个涉及的表上重新编译,或者dbcc freeproccache将强制执行新的执行计划……哦,使用探查器,您可以获得L2S命中数据库的确切SQL查询。在您的问题中,以“declare”语句开头的语句不是L2S对db的影响。L2S将使用sp_executesql来运行它,以确保它最终在存储的过程计划缓存中…我仍然没有得到它。我正在执行与查询转换成的SQL完全相同的SQL,并且它在SQL Management Studio中运行良好。同样在Linqpad(执行SQL查询)中。如果是缓存的执行计划问题,那么生成的sql(即相同的sql)不也应该有相同的问题吗?同样,L2S不会生成以“declare…”开头的sql语句。该部分由用于提取查询的任何工具生成。(林帕德?)。L2S发送到数据库的实际语句应该类似于“exec sp_executesql N'SELECT DISTINCT[t5]…”、“@p0 int、@p1 int、@p2 int”、@p0=196、@p1=20100101……”。运行与L2S命中数据库的查询完全相同的查询之外的其他操作,您没有使用相同的缓存计划,因此在缓存随机错误计划的情况下,将不会看到相同的行为。。。