我有一个在正常情况下运行相当快的查询。但由于筛选器中有多少值,它的运行速度非常慢(在 SSMS 中至少需要 20 分钟(。
这是它的通用版本,您可以看到一个部分正在过滤超过 8,000 个值,使其运行缓慢。
SELECT DISTINCT
column
FROM
table_a a
JOIN
table_b b ON (a.KEY = b.KEY)
WHERE
a.date BETWEEN @Start and @End
AND b.ID IN (... over 8,000 values)
AND b.place IN ( ... 20 values)
ORDER BY
a.column ASC
它已经到了太慢而无法在生产应用程序中使用的地步。
有谁知道如何解决这个问题,或优化查询?
若要快速查询,需要索引。您需要为以下列提供单独的索引:a.KEY、b.KEY、a.date、b.ID、b.place。正如 gotqn 之前所写,如果您将 8000 个项目放入临时表并内部联接它,它也会使查询更快,但如果没有联接另一部分的索引,即使这样也会很慢。
的是将过滤值放在临时表中。然后使用该表通过 INNER JOIN
而不是 WHERE IN
来应用筛选。例如:
IF OBJECT_ID('tempdb..#FilterDataSource') IS NOT NULL
BEGIN;
DROP TABLE #FilterDataSource;
END;
CREATE TABLE #FilterDataSource
(
[ID] INT PRIMARY KEY
);
INSERT INTO #FilterDataSource ([ID])
-- you need to split values
SELECT DISTINCT column
FROM table_a a
INNER JOIN table_b b
ON (a.KEY = b.KEY)
INNER JOIN #FilterDataSource FS
ON b.id = FS.ID
WHERE a.date BETWEEN @Start and @End
AND b.place IN ( ... 20 values)
ORDER BY .column ASC;
几个重要注意事项:
- 我们使用临时表以允许使用并行执行计划
- 如果您有用于吐痰的快速(例如 CLR 函数(,则可以加入函数本身
- 使用具有许多值的
IN
是不好的,SQL Server无法始终构建可能导致超时/内部错误的执行计划 - 您可以在此处找到更多信息