除了让查询本身更快响应的变通方法之外,您是否考虑过在表中维护一个列来说明它是否在这个集合中?它需要大量维护,但如果ExcludedCodes
表不经常更改,那么进行维护可能会更好。例如,您可以添加一个 BIT 列:
ALTER TABLE dbo.Table1 ADD IsExcluded BIT;
将其设为 NOT NULL 并默认为 0。然后您可以创建过滤索引:
CREATE INDEX n ON dbo.Table1(name)
WHERE IsExcluded = 0;
现在您只需更新表一次:
UPDATE t
SET IsExcluded = 1
FROM dbo.Table1 AS t
INNER JOIN dbo.ExcludedCodes AS x
ON t.Code = x.Code;
并且正在进行中,您必须使用两个表上的触发器来维护它。有了这个,您的查询变为:
SELECT @Count = COUNT(Name)
FROM dbo.Table1 WHERE IsExcluded = 0;
编辑
至于“NOT IN 比 LEFT JOIN 慢”,这是我仅在几千行上执行的简单测试:
编辑 2
我不确定为什么这个查询不会做你所追求的,并且比你的 40K 循环更有效率:
SELECT src.Name, COUNT(src.*)
FROM dbo.Table1 AS src
INNER JOIN #temptable AS t
ON src.Name = t.Name
WHERE src.Code NOT IN (SELECT Code FROM dbo.ExcludedCodes)
GROUP BY src.Name;
或 LEFT JOIN 等价物:
SELECT src.Name, COUNT(src.*)
FROM dbo.Table1 AS src
INNER JOIN #temptable AS t
ON src.Name = t.Name
LEFT OUTER JOIN dbo.ExcludedCodes AS x
ON src.Code = x.Code
WHERE x.Code IS NULL
GROUP BY src.Name;
我会在不到 27 分钟的时间内将钱花在其中任何一个查询上。我什至建议按顺序运行这两个查询将比您需要 27 分钟的一个查询快得多。
最后,您可能会考虑使用索引视图。我不知道您的表结构以及您是否违反任何限制,但值得调查恕我直言。