可能是参数嗅探。
当调用存储过程并且缓存中没有与该存储过程匹配的现有执行计划时set
连接的选项将使用该调用中传入的参数值来编译新的执行计划。
有时,当传递的参数不典型(例如具有异常高的选择性)时会发生这种情况,因此生成的计划将不适合具有不同参数的大多数其他调用。
SSMS 对该选项有不同的默认值SET ARITH_ABORT
因此,当您在 SSMS 内执行存储过程时,不会遇到同样有问题的计划。
下次发生这种情况时,调查该问题的最简单方法可能是使用 2 个独立的 SSMS 窗口,并启用“包括实际执行计划”选项,并在一个窗口中执行以下操作:
SET ARITHABORT OFF
EXEC YourProc ...
而在另一个
SET ARITHABORT ON
EXEC YourProc ...
假设使用默认的 ADO.NET 和 SSMS 连接选项,第一个选项应使用缓存中的错误计划。
如果这对您不起作用,您可以使用探查器查看您需要修改哪些其他设置选项才能获得错误计划,或者仅使用探查器直接获取执行计划 - 或者您可以从 DMV 检索它们,如下所示。
select p.query_plan, *
from sys.dm_exec_requests r
cross apply sys.dm_exec_query_plan(r.plan_handle) p
where r.session_id = <spid of your ADO.NET connection>
例如,您可能会发现有问题的计划正在执行数以万计的单独索引搜索,而好的计划则避免了这种情况。