我有这个 SQL 语句:
select *
from _my_table1
where 1 = 0
and (exists (select 1 from _my_table2 where id =7))
执行计划是:
|--Constant Scan
现在,当我将查询更改为
Declare @i int = 1
SELECT *
FROM dbo._my_table1
WHERE @i = 0 AND (EXISTS (SELECT 1 FROM dbo._my_table2 WHERE id = 7))
我得到以下计划:
|--Nested Loops(Left Semi Join)
|--Filter(WHERE:(STARTUP EXPR([@i]=(0))))
| |--Clustered Index Scan(OBJECT:([DEV-RWA_IECMS-DE_Staging_20160301].[dbo].[_my_table1].[PK___my_tabl__3213E83FEF434214]))
|--Clustered Index Seek(OBJECT:([DEV-RWA_IECMS-DE_Staging_20160301].[dbo].[_my_table2].[PK___my_tabl__3213E83F4D4FA6E2]), SEEK:([DEV-RWA_IECMS-DE_Staging_20160301].[dbo].[_my_table2].[id]=(7)) ORDERED FORWARD)
WHERE
问题是如果第一部分返回 false,为什么 SQL Server 检查子句的第二部分。如果第一部分返回 false,是否有任何解决方法强制 SQL 引擎不检查 where 的第二部分。
OPTION (RECOMPILE)
是你的朋友。SQL Server 不知道@i
执行时的值是什么,因此它编译了一个适用于任何参数值的计划。强制重新编译将覆盖该行为并生成具有持续扫描的计划。
例子:
如果您捕获实际的执行计划,它将只包含一个常量扫描。没有
OPTION (RECOMPILE)
它包含常规计划。