SQL 当 IN 子句中的项目数超过 4 时,服务器查询非常慢

SQL Server query is very slow when number of items inside IN clause more than 4

我有一些复杂的查询,其中包含许多表的连接。由于复杂性,很难进行真正的查询。

有点像

select t1.id, t2.id, t1.name, t2.name 
from table1 t1, table2 t2
left join table3 t3 ON t2.id = t3.id
where t2.id = t1.ref_id
  and t1.ref_id IN ('id1', 'id2', 'id3', 'id4', 'id5', ...)

我发现,如果我在 IN 子句中只有 4 个或更少这样的值 t1.ref_id IN ('id1', 'id2', 'id3', 'id4') 它工作得非常快(16 毫秒)。如果我只添加一个 id 并使它像这样 t1.ref_id IN ('id1', 'id2', 'id3', 'id4', 'id5') 执行时间增加到40倍,变成600毫秒

我在 SQL Server 2014 上得到它。

似乎有一些参数可以控制此行为。我在另一个 SQL 服务器(SQL Server 2008)中尝试了这个查询,但我找不到任何限制。

我的问题:是否有控制这种行为的参数?或者如何将这个奇怪的限制增加到 50。

我只想将它增加到 30-50 而不是 4。当然我不想创建具有成百上千个值的 IN 子句。

更新 1

抱歉,忘记把t3.name改成select了,不然t3好像不需要了:

select t1.id, t2.id, t1.name, t2.name, t3.name
from table1 t1, table2 t2
left join table3 t3 ON t2.id = t3.id
where t2.id = t1.ref_id
  and t1.ref_id IN ('id1', 'id2', 'id3', 'id4', 'id5', ...)

更新2

看来我找到原因了。问题不在于 IN 中的项目数量。后来我用少于 4 个 id 重现了这个问题(即使有 1 个)。它发生了,因为一些 ids 没有出现在 t1.ref_id 中。当存在 t1.ref_id 中不存在的 id 时,当它很快时,当我添加 id 时,t1.ref_id 中确实存在,当它变慢时。在我之前的示例中,id1 - id4 未出现在 t1.ref_id 中,而 id5 出现了。这就是为什么当我添加 id5 时它变慢了。即使我只在 IN 子句中放入 1 个 id (id5),它也会变慢。最后 t1.ref_id 上的索引解决了这个问题。围绕 4 或 5 个 id 没有魔法。我的具体例子纯属巧合

首先,修复查询。简单规则:从不FROM 子句中使用逗号。

select t1.id, t2.id, t1.name, t2.name 
from table1 t1 join
     table2 t2
     on t2.id = t1.ref_id left join
     table3 t3 
     on t2.id = t3.id
where t1.ref_id in ('id1', 'id2', 'id3', 'id4', 'id5', ...);

根据查询,您不需要 table3 -- 除非您关心重复的行。我会删除它。

然后,你需要考虑索引。我会建议 table1(ref_id, id, name)table2(id, name).

此外,如果 ref_id 确实是一个数字,则不要在列表中的值两边加上单引号。混合字符串和数字会使优化器感到困惑。