排序运算符在执行计划中的定位

jes*_*esi 5 performance sql-server execution-plan sql-server-2014 query-performance

我正在对性能问题进行故障排除并尝试为报告查询获得稳定的执行计划。实际计划的链接如下:

VS

如果您查看 Good 计划,则排序是在表连接之后进行的。对于糟糕的计划,排序就在最后一个连接之前。在错误计划的情况下,因为排序在最后一个连接之前,并且排序的估计行数为 5000,SQL Server 决定使用嵌套循环连接,这会减慢查询速度。

我不想使用表连接提示或更改TOP.

在这种情况下,我可以使用哪些策略来获得一致的计划?

此查询大约每 5 分钟运行一次。

Joe*_*ish 3

看来您遇到了经典的参数嗅探问题。据我所知,您的查询是相同的,但它们都使用不同的缓存计划。您获得的缓存计划取决于第一次运行的输入参数。我假设有一个计划对于所有输入都足够有效,并且您想要该计划。然而,根据参数值,您可能会运气不好,最终得到一个对某些输入效果更好但对其他输入效果不佳的计划。

RECOMPILE如果可能的话,我会在查询中添加提示。这将阻止查询优化器使用缓存的查询计划,但它会在制定计划时看到变量的值。作为一般经验法则,如果您可以向优化器提供更多信息,您将获得更好的性能。这种方法的缺点是每次都会重新编译查询计划,但这只是一个三表查询。除非查询每秒运行数百次,否则我不会担心它。

另一种选择是使用OPTIMIZE FOR 查询提示。这将为您提供一个不基于输入值的缓存计划,因此关键是获得一个适用于所有可能的输入值的查询计划。在您的另一个问题中,您暗示您对 100 行的默认猜测不满意,TOP因此您可以强制查询优化器针对特定TOP值进行优化,如下所示:

OPTION (OPTIMIZE FOR UNKNOWN, OPTIMIZE FOR (@top = 5000));
Run Code Online (Sandbox Code Playgroud)

不会嗅探任何输入变量来形成计划。该语法可能看起来很奇怪,但它是允许的:

如果在同一查询提示中使用 OPTIMIZE FOR @variable_name =literal_constant 和 OPTIMIZE FOR UNKNOWN,则查询优化器将使用为特定值指定的literal_constant,并为其余变量值使用 UNKNOWN。这些值仅在查询优化期间使用,而不在查询执行期间使用。

如果这些选项都不起作用,并且您确信自己有一个运行良好的查询计划,则可以考虑使用计划指南。