选项(重新编译)可加快查询执行速度

时间:2016-06-17 19:40:26

标签: sql-server

将此问题作为一个更广泛的问题发布,但如果实际查询有助于解决此问题,请告诉我。

根据执行计划判断,我们有一个查询需要大约30秒才能运行。查询是由实体框架生成的,当然也存在一些效率低下的问题,因此不是重点。

当我们DBCC FREEPROCCACHE并提交查询时,原来~30秒运行时间。当使用OPTION(RECOMPILE)暗示查询时,它是即时的(并且计划更加合理)。

如果查询在第一个场景中第一次到达服务器,为什么结果会有所不同,因此第一次编译计划也是如此?

附注:

更新 - 添加计划:

1 个答案:

答案 0 :(得分:1)

这看起来不像参数嗅探。

CompiledValue和RunTimeValue对于所有参数都是相同的,即使在bad.sqlplan

中也是如此
OPTION (RECOMPILE)

相反,您似乎从The Parameter Embedding Optimization中受益。

查询文本在计划中被截断,但我可以看到您将参数与文字进行比较的位置。也许这是catch all query

enter image description here

当您使用TRUE时,编译的计划必须适用于传递的参数值。 SQL Server可以查看传递的参数的值,并使用FALSEEXEC sys.sp_executesql N'SELECT * FROM master..spt_values WHERE @Param <> 0 OPTION (RECOMPILE)', N'@Param INT', @Param = 0; 有效地替换突出显示的表达式。

如果它们与传递的参数值无关,则可能允许它简化计划的整个分支。

一个简单的例子就是

@Param=0

计划是在@Param <> 0时编译的,而只需要对此值是正确的,因此可以在编译时将false评估为OPTION (RECOMPILE)并且该计划根本无法访问该表。

enter image description here

没有EXEC sys.sp_executesql N'SELECT * FROM master..spt_values WHERE @Param <> 0', N'@Param INT', @Param = 0; ,你会看到这个

int increment(int* index, int N, int len)
{
    for (int i = N - 1; i >= 0; --i)
    {
        ++index[i];
        if (index[i] < len)
            return 1;
        index[i] = 0;
    }
    return 0;   
}

enter image description here

即使嗅探参数值和运行时参数值相同,计划也无法优化到与缓存相同的程度,如果传递了不同的参数值仍然需要工作。