我有一个LINQ to SQL查询,它生成以下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 Server 2008上SQL Profiler的实际SQL。)
从Query Analyser
内运行此SQL时生成的查询计划是完美的。
它使用包含VisitedStore
,Bot
,SessionDate
的索引。
查询立即返回。
然而,当我从C#(使用LINQ)运行它时,使用了一个效率非常低的不同查询计划,它甚至不会在60秒内返回。此查询计划尝试对包含数百万行的群集主键执行密钥查找。它没有机会回来。
我无法理解的是,正在运行EXACT相同的SQL - 无论是在LINQ内还是在查询分析器中,查询计划都不同。
我已多次运行这两个查询,现在它们与其他查询隔离运行。日期是DateTime.Now.AddDays(-7)
,但我甚至硬编码该日期以消除缓存问题。
我是否可以在LINQ to SQL中更改任何影响查询计划或尝试进一步调试的内容?我非常困惑!
答案 0 :(得分: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查询。
答案 1 :(得分:0)
切换到存储过程,相同的SQL工作正常。我真的很想知道发生了什么,但现在不能再花这么多时间了。幸运的是,在这种情况下,查询不是太动态。
希望这至少可以帮助与我同舟共济的人