Joe*_*nos 12 c# sql-server asp.net entity-framework
我已经在Windows 2008R2中的ASP.NET上运行了.NET 4.5的Entity Framework 4.1.我使用EF代码优先连接到SQL Server 2008R2,并执行相当复杂的LINQ查询,但只产生了一个Count().
我在两个不同的Web服务器上重现了这个问题,但只有一个数据库(当然是生产).它最近开始在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]'
Run Code Online (Sandbox Code Playgroud)
编辑
我不是将此作为答案添加,因为它实际上并没有解决潜在的问题,但最终通过重建索引和重新计算统计数据来解决这个问题.没有比平时更长的时间,这似乎已经解决了造成这个问题的任何问题.
我会继续阅读这里的一些链接,以防再次发生这种情况,但由于它现在都在工作并且无法实现,我不知道我是否确实知道它到底在做什么.
感谢所有的想法.
我最近有一个非常类似的场景,一个查询将在数据库中直接执行它非常快,但使用EF(在我的情况下版本5)有可怕的性能.这不是一个网络问题,差异是从4毫秒到10分钟.
问题最终成为映射问题.我有一个映射到的列NVARCHAR,而它VARCHAR在数据库中.似乎无害,但这导致数据库中的隐式转换,这完全破坏了性能.
我不完全确定为什么会发生这种情况,但是从我做的测试中,这导致数据库执行索引扫描而不是索引搜索,显然它们在性能方面有很大不同.

我在这里写博客(免责声明:它是葡萄牙语),但后来我发现Jimmy Bogard在2012 年的帖子中描述了这个确切的问题,我建议你看一下.
既然你的查询中有转换,我会说从那里开始.仔细检查所有列映射,并检查表的列与实体属性之间的差异.避免在查询中进行隐式转换.
如果可以,请检查执行计划以找出任何不一致的地方,请注意黄色警告三角形,它可能表示有关进行隐式转换的问题:

我希望这能以某种方式帮助你,这对我们来说是一个非常难以找到的问题,但最终还是有意义的.
这里有一篇关于实体框架性能考虑的优秀文章。
我想提请您注意冷查询执行与热查询执行的部分:
第一次针对给定模型进行任何查询时,实体框架会在幕后执行大量工作来加载和验证模型。我们经常将第一个查询称为“冷”查询。针对已加载模型的进一步查询称为“热”查询,并且速度要快得多。
在 LINQ 查询执行期间,“元数据加载”步骤对冷查询执行的性能有很大影响。但是,一旦加载元数据将被缓存,并且将来的查询将运行得更快。元数据缓存在 DbContext 外部,并且只要应用程序池存在,就可以重复使用。
为了提高性能,请考虑以下操作:
所有这些要点都在上面提供的链接中得到了详细记录。此外,您还可以在此处找到有关创建实体框架本机映像的更多信息。
| 归档时间: |
|
| 查看次数: |
4527 次 |
| 最近记录: |