我遇到了一个奇怪的现象,然后调查了一个典型的ASP.NET MVC应用程序的慢视图。其中一个查询运行速度非常慢,没有明显的原因。有问题的LINQ查询看起来像这样(Db
是DbContext
):
var testResults = Db.CustomTestResults
.Include(tr => tr.TestMachine.Platform)
.Include(tr => tr.TestCase)
.Include(tr => tr.CustomTestResultAnalysis.Select(tra => tra.AnalysisOutcomeData))
.Where(tr => tr.CustomTestBuildId == testBuild.Id)
.ToList()
.AsReadOnly();
实际上没什么特别的。根据过滤器查询结果集的大小可能会有所不同,最大值为10到10000条记录
从SSMS执行的SQL生成的查询(由LINQ调试日志捕获)运行速度很快,最大集合大约需要2秒,小集合运行不到1秒。然而,由IIS运行奇怪的事情发生。查询开始运行速度慢~1 / 100x。较小的执行需要大约10秒,由于查询执行超时,较大的执行失败。我不确定是否有任何其他查询受到影响,但这只是处理大型数据集,所以注意到这个问题最为明显。
由于这并不令人困惑,因此相同的代码在不久前的预期中运行得非常完美。所以这个bug似乎是由一些外部因素造成的。数据库是SQL Server 2014 SP2,EF是v6.2,IIS 7.5。
非常感谢在哪些方面有任何想法,以及我如何进一步调查这一点。
答案 0 :(得分:1)
事实证明,问题出在SQL Server优化中,它在多次运行类似查询后开始运行一段时间。可以通过对原始查询的任何非相关更改来检测此问题,这会在一段时间内修复性能。
controlling query command options可以正确缓解此行为。 EF的解决方案之一是demonstrated here。
作为一种临时的“快速而肮脏”的解决方案,我每次都使用这种方法随机化查询,从而阻止了SQL Server引擎的优化:
private static IQueryable<CustomTestResult> RandomizeQuery(IQueryable<CustomTestResult> query)
{
const int minConditions = 1;
const int maxConditions = 5;
const int minId = -100;
const int maxId = -1;
var random = new Random();
var conditionsCount = random.Next(minConditions, maxConditions);
for (int i = 0; i < conditionsCount; i++)
{
var randomId = random.Next(minId, maxId);
query = query.Where(test => test.Id != randomId);
}
return query;
}
答案 1 :(得分:0)
由于SQL没有改变但是根据你运行的平台出现问题,我会从你的设置开始。 Erland Sommarskog写了一篇关于为什么和做什么的伟大参考:http://www.sommarskog.se/query-plan-mysteries.html
很长,但我想你会在那里找到答案。