假设我们的存储过程表现不佳,有6个参数.如果六个参数中的一个被转移到存储过程中的局部变量,那是否足以禁用参数嗅探或是否需要将传递给存储过程的所有6个参数传输到存储过程中的局部变量?
根据Paul White的评论,将变量分配给局部变量是旧版SQL Server的解决方法.它无济于事sp_executesql,微软可以编写一个更智能的解析器来解决这个问题.解决方法的工作原理是将解析器与参数的值混淆,因此为了使其适用于每个参数,您必须将每个参数存储在局部变量中.
更新版本的SQL Server有更好的解决方案.对于不经常运行的昂贵查询,我会使用option (recompile).例如:
SELECT *
FROM YourTable
WHERE col1 = @par1 AND col2 = @par2 AND ...
OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)
这将导致查询计划程序在每次调用存储过程时重新创建("重新编译")计划.鉴于规划的低成本(通常低于25毫秒),这对于昂贵的查询来说是明智的行为.值得25ms来检查您是否可以为250ms查询创建特定参数的更智能的计划.
如果您的查询经常运行,以至于计划成本非常重要,您可以使用option (optimize for unknown).这将导致SQL Server创建一个计划,它希望能够很好地适用于所有参数的所有值.当您指定此选项时,SQL Server会忽略参数的第一个值,因此这实际上可以防止嗅探.
SELECT *
FROM YourTable
WHERE col1 = @par1 AND col2 = @par2 AND ...
OPTION (OPTIMIZE FOR UNKNOWN)
Run Code Online (Sandbox Code Playgroud)
此变体适用于所有参数.您可以使用optimize for (@par1 unknown)以防止仅嗅探一个参数.
| 归档时间: |
|
| 查看次数: |
772 次 |
| 最近记录: |