将此问题作为一个更广泛的问题发布,但如果实际查询有助于解决此问题,请告诉我。
根据执行计划判断,我们有一个查询需要大约30秒才能运行。查询是由实体框架生成的,当然也存在一些效率低下的问题,因此不是重点。
当我们DBCC FREEPROCCACHE并提交查询时,原来~30秒运行时间。当使用OPTION(RECOMPILE)暗示查询时,它是即时的(并且计划更加合理)。
如果查询在第一个场景中第一次到达服务器,为什么结果会有所不同,因此第一次编译计划也是如此?
附注:
更新 - 添加计划:
答案 0 :(得分:1)
这看起来不像参数嗅探。
CompiledValue和RunTimeValue对于所有参数都是相同的,即使在bad.sqlplan
中也是如此OPTION (RECOMPILE)
相反,您似乎从The Parameter Embedding Optimization中受益。
查询文本在计划中被截断,但我可以看到您将参数与文字进行比较的位置。也许这是catch all query
当您使用TRUE
时,编译仅的计划必须适用于传递的参数值。 SQL Server可以查看传递的参数的值,并使用FALSE
或EXEC 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)
并且该计划根本无法访问该表。
没有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;
}
即使嗅探参数值和运行时参数值相同,计划也无法优化到与缓存相同的程度,如果传递了不同的参数值仍然需要工作。