代码之家  ›  专栏  ›  技术社区  ›  pabdulin

根据执行上下文,相同的SQL查询是快还是慢

  •  2
  • pabdulin  · 技术社区  · 8 年前

    我遇到了一个奇怪的现象,然后调查了一个典型的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 debug log捕获)运行速度很快,对于最大的集大约为2秒,对于较小的集不到1秒。然而,然后由IIS运行奇怪的事情发生了。查询开始以大约1/100倍的速度运行。较小的需要大约10秒才能执行,较大的则由于查询执行超时而失败。我不确定是否有任何其他查询受到影响,但这只是处理大型数据集的查询,因此最明显的是要注意这个问题。

    因为这还不够混乱,所以不久前,这段代码就像预期的那样完美地运行着。所以这个bug似乎是由一些外部因素引起的。数据库为SQL Server 2014 SP2,EF为v6.2,IIS 7.5。

    如果您有任何关于哪些方面以及我如何进一步调查的想法,我将不胜感激。

    2 回复  |  直到 8 年前
        1
  •  1
  •   pabdulin    8 年前

    事实证明,问题出在SQL Server优化上,在多次运行类似查询后,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;
    }
    
        2
  •  0
  •   JMabee    8 年前

    由于SQL没有改变,但它有问题,这取决于您运行的平台,我将从您的设置开始。Erland Sommarskog写了一篇关于为什么和如何的很好的参考: http://www.sommarskog.se/query-plan-mysteries.html

    这很长,但我想你会在那里找到你的答案。