对一个表进行简单选择查询时出现消息 8623,级别 16,状态 1,第 1 行错误

Min*_*dan 3 sql t-sql sql-server subquery sql-in

如何优化在一个表中搜索不属于一组的 ID 的简单查询。

我创建了以下查询

Select userId 
from user 
where userId not in (5000, 5001, 5002, 5003, more....)
Run Code Online (Sandbox Code Playgroud)

请注意,该列表包含超过 35000 行。我收到以下数据库错误

消息 8623,级别 16,状态 1,第 1 行
查询处理器耗尽内部资源,无法生成查询计划。这是一种罕见的事件,仅适用于极其复杂的查询或引用大量表或分区的查询。

有些人建议通过使用左连接来优化查询,但我只是在一个表中搜索,那么还有什么选择呢?

GMB*_*GMB 6

这是有记录的行为

在子句中的括号内显式包含大量值(用逗号分隔的数千个值)IN可能会消耗资源并返回错误 8623 或 8632。要解决此问题,请将列表中的项目存储在IN表中,并在子句SELECT中使用子查询IN

35000 显然符合数千人的资格。因此,根据文档,您应该创建一个表(或临时表)来存储您的值,然后left join如下所示:

select u.userId 
from user u
left join mytemptable t on t.userId = u.userId
where t.userId  is null
Run Code Online (Sandbox Code Playgroud)

您还可以使用not exists

select u.userId
from user u
where not exists (select 1 from mytemptable t where t.userId = u.userId)
Run Code Online (Sandbox Code Playgroud)

作为奖励,请注意,使用上述技术之一可以修复原始查询的空安全问题(事实上,如果列表中的任何值是 ,则无论 的值IN如何NULLNOT IN条件都将被视为满足userId) 。