知道为什么IF EXISTS
它将使它运行更长的时间并进行更多的读取吗?我也将select语句更改为do,SELECT TOP 1 [dlc].[id]
并在2分钟后将其杀死。
正如我在对这个相关问题的回答中所解释的:
TOP如何(以及为什么)影响执行计划?
使用EXISTS
引入了行目标,优化程序在该目标中生成旨在快速定位第一行的执行计划。在此,假定数据是均匀分布的。例如,如果统计数据显示在100,000行中有100个预期的匹配项,则将假定它仅需读取1,000行即可找到第一个匹配项。
如果此假设有误,这将导致比预期的执行时间更长的时间。例如,如果SQL Server选择的访问方法(例如无序扫描)恰好在搜索中很晚才找到第一个匹配值,则可能导致几乎完整的扫描。另一方面,如果恰好在前几行中找到匹配的行,则性能将非常好。这是行目标的基本风险-不一致的性能。
作为临时解决方案,我将其更改为执行count(*)并将该值分配给变量
通常可以重新构造查询,以便不分配行目标。如果没有行目标,则遇到第一个匹配的行(如果写正确)时,查询仍然可以终止,但是执行计划策略可能会有所不同(并且希望更有效)。显然,count(*)将需要读取所有行,因此这不是一个完美的选择。
如果运行的是SQL Server 2008 R2或更高版本,则通常还可以使用已记录并受支持的跟踪标志4138来获得没有行目标的执行计划。也可以使用受支持的提示 来指定此标志OPTION (QUERYTRACEON 4138)
,但是请注意,除非与计划指南一起使用,否则它需要运行时sysadmin权限。
不幸
以上所有IF EXISTS
条件均不能使用条件语句。它仅适用于常规DML。它会用交替工作SELECT TOP (1)
,你试过配方。COUNT(*)
如前所述,这可能比使用必须计数所有合格行的更好。
就是说,有多种方法可以表达此要求,使您能够避免或控制行目标,同时尽早终止搜索。最后一个例子:
DECLARE @Exists bit;
SELECT @Exists =
CASE
WHEN EXISTS
(
SELECT [dlc].[ID]
FROM TableDLC [dlc]
JOIN TableD [d]
ON [d].[ID] = [dlc].[ID]
JOIN TableC [c]
ON [c].[ID] = [d].[ID2]
WHERE [c].[Name] <> [dlc].[Name]
)
THEN CONVERT(bit, 1)
ELSE CONVERT(bit, 0)
END
OPTION (QUERYTRACEON 4138);
IF @Exists = 1
BEGIN
...
END;
IF NOT EXISTS (...) BEGIN END ELSE BEGIN <do something> END
。