【发布时间】:2015-03-24 20:41:07
【问题描述】:
我在 Windows 2008R2 的 ASP.NET 上运行了带有 .NET 4.5 的 Entity Framework 4.1。我使用 EF 代码优先连接到 SQL Server 2008R2,并执行一个相当复杂的 LINQ 查询,但结果只是一个 Count()。
我已经在两台不同的网络服务器上重现了这个问题,但只有一个数据库(当然是生产)。它最近开始发生,在 Web 或数据库端没有应用程序、数据库结构或服务器更改。
我的问题是在某些情况下执行查询会花费大量时间(接近 4 分钟)。我可以从 SQL Profiler 中提取实际查询,并在大约 1 秒内在 SSMS 中执行。这对我来说是一致且可重现的,但是如果我将其中一个参数(“2015-01-22 之后的日期”参数)的值更改为更早的值,例如 2015-01-01,或者更晚的值,例如 2015-02- 01,它在EF中运行良好。但我把它放回 2015-01-22 又变慢了。我可以一遍又一遍地重复。
然后我可以在 EF 中运行一个类似但不相关的查询,然后返回到原始查询,这次它运行良好 - 与以前完全相同的查询。但是如果我打开一个新的浏览器,循环又会重新开始。这部分也没有任何意义——我们没有做任何事情来保留用户会话中的数据上下文,所以我不知道为什么会这样。
但这一切都告诉我数据本身是好的。
在 Profiler 中,当查询正常运行时,大约需要一两秒,并显示大约 2,000,000 次读取和大约 2,000 次 CPU。当它运行缓慢时,需要 3.5 分钟,并且值是 300,000,000 和 200,000 - 所以读取量大约高出 150 倍,CPU 高出 100 倍。同样,对于相同的 SQL 语句。
关于 EF 可能会做哪些不同但不会出现在查询文本中的任何建议?是否存在某种隐藏的连接属性,在某些情况下可能会导致不同的执行计划?
编辑
EF 构建的查询是其中一种使用包含在文本中的参数而不是 SQL 参数来构建巨型字符串的查询:
exec sp_executesql
N'SELECT [GroupBy1].[A1] AS [C1]
FROM (
SELECT COUNT(1) AS [A1]
...
AND ([Extent1].[Added_Time] >= convert(datetime2, ''2015-01-22 00:00:00.0000000'', 121))
...
) AS [GroupBy1]'
编辑
我没有将其添加为答案,因为它实际上并没有解决根本问题,但这最终通过重建索引和重新计算统计信息得到解决。这并没有比平时更久,而且似乎已经解决了导致问题的任何原因。
我会继续阅读这里的一些链接,以防再次发生这种情况,但由于现在一切正常且无法重现,我不知道我是否能确切知道它在做什么。
感谢所有的想法。
【问题讨论】:
-
这对我来说听起来像是错误的参数嗅探。查看有关该主题的这篇文章。 sqlinthewild.co.za/index.php/2007/11/27/parameter-sniffing(确保您阅读了所有三个部分)
-
@Guvante 我很想在 SSMS 中重现,但无论我做什么,它总是从那里运行良好。这也让 DBA 更难提供帮助,因为他们无法重现它。
-
@SergueiFedorov 似乎总体上可以很好地扩展。在 SSMS 中,当应用程序运行时,查询运行良好。我们在主表中有几十万条记录,即使在无限日期范围内执行此查询,它也会在几秒钟内返回。
-
可能有用:Slow in the Application, Fast in SSMS? Understanding Performance Mysteries。 SSMS 使用与 ADO.NET 不同的查询选项,因此它可能不会使用相同的缓存查询计划,这解释了为什么您无法重现 SSMS 的减速。您是否尝试过更新统计信息? (链接的文章还有其他故障排除建议。)
-
@Ewan 你不会在 10 毫秒内获得 200 万次读取。检查丢失的索引可能更重要...
标签: c# asp.net sql-server entity-framework