2010-02-22 28 views
10

我有一个LINQ to SQL的查询,生成的SQL语句:'LINQ查询计划'可怕的效率很低,但'查询分析器查询计划'对于相同的SQL是完美的!

exec sp_executesql N'SELECT COUNT(*) AS [value] 
FROM [dbo].[SessionVisit] AS [t0] 
WHERE ([t0].[VisitedStore] = @p0) AND (NOT ([t0].[Bot] = 1)) AND 
([t0].[SessionDate] > @p1)',N'@p0 int,@p1 datetime', 
@p0=1,@p1='2010-02-15 01:24:00' 

(这是从SQL事件探查器SQL Server 2008上所采取的实际SQL)

当我运行这个生成的查询计划Query Analyser中的SQL是完美的。 它使用索引包含VisitedStore,Bot,SessionDate。 查询立即返回。

但是,当我从C#(使用LINQ)运行这个不同的查询计划时,效率非常低,甚至不会在60秒内返回。此查询计划试图对包含几百万行的聚集主键进行密钥查找。它没有返回的机会。

我只是不明白,但是EXACT正在运行相同的SQL - 无论是从LINQ内部还是从查询分析器内部查询计划都不同。

我已经跑了两次查询很多次,他们现在正在孤立于任何其他查询运行。日期是DateTime.Now.AddDays(-7),但我甚至对该日期进行了硬编码以消除缓存问题。

有没有什么我可以改变的LINQ to SQL来影响查询计划或尝试进一步调试呢?我非常困惑!

+0

如何查看执行计划,在不同的语境:http://stackoverflow.com/questions/7359702/how-do-i-obtain-a-查询执行计划 –

回答

6

这是一个比较常见的问题,当我第一次看到它的时候也让我感到吃惊。首先要做的是确保您的统计数据是最新的。您可以通过以下方式查看统计年龄:

SELECT 
    object_name = Object_Name(ind.object_id), 
    IndexName = ind.name, 
    StatisticsDate = STATS_DATE(ind.object_id, ind.index_id) 
FROM SYS.INDEXES ind 
order by STATS_DATE(ind.object_id, ind.index_id) desc 

统计信息应在每周维护计划中更新。为了速战速决,发出以下命令来更新数据库中的所有统计信息:

exec sp_updatestats 
从统计

除此之外,你可以检查另一件事是SET options。查询分析器和你的Linq2Sql应用程序可以不同。

另一种可能是SQL Server为您的Linq2Sql查询使用旧的缓存计划。计划可以基于每个用户进行缓存,因此如果将查询分析器作为其他用户运行,则可以解释不同的计划。通常情况下,您可以将Option (RECOMPILE)添加到应用程序查询中,但是我认为使用Linq2Sql很困难。您可以用DBCC FREEPROCCACHE清除整个缓存,并查看是否加快了Linq2Sql查询速度。

+0

我跑了大约7分钟的sp_updatestats。然后我跑了没有错误立即返回的DBCC FREEPROCCACHE。仍然是相同的行为。您提供的SELECT将显示所有统计数据的现在日期(其中一些统计数据是在2岁以前!)。我可能不得不尝试使用存储过程。生病尝试明天比较SET选项。谢谢! –

+0

btw。即使在LINQ中,如果日期在最近48小时内(似乎没有确定这是哪种查询计划,但可能没有足够的行以至于扫描没有问题),似乎也很正常。一旦我超过约60小时,它切换到另一个查询计划,并永远不会返回。但从查询分析器我可以做一个月,一年,两年,它立即返回(这是一个233000行的计数)!再次来自profiler的同样精确的SQL。更奇怪的是... –

+0

如果你的第一个LINQ查询在48小时内,SQL Server可能会生成一个优化的计划。如果您使用'dbcc freeproccache'并且第一个查询超过60小时会发生什么?另外考虑使用ExecuteQuery(http://msdn.microsoft.com/en-us/library/bb399403.aspx)重写Linq2Sql,它允许你指定'选项(重新编译)' – Andomar

0

切换到存储过程和相同的SQL工作正常。我们真的很想知道发生了什么,但现在不能再花更多时间了。幸运的是,在这种情况下,查询不是太动态。

希望这至少有助于在同一条船上的人是我