SQL 服务器:使用 3 "OR" 条件和按 ID 排序的慢查询
SQL Server : slow query with 3 "OR" condition and order by Id
我的查询:
SELECT TOP 30 a.*
FROM Car
WHERE (ModelId = 642 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15)) OR
(ModelId = 242 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15, 26)) OR
(ModelId = 334 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15, 26))
ORDER BY Id DESC
它在 30 秒内执行。
如果我删除 order by Id
部分,它会在 1 秒内执行。
或者如果我删除一个 OR
条件,它也会在 1 秒内执行。
WHERE (ModelId = 642 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15)) OR
(ModelId = 242 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15, 26))
ORDER BY Id DESC
列 ModelId
和 RegionId
有索引。 Id
是主键。
执行计划显示 97% 的聚簇索引搜索了 Id。
请帮帮我。为什么 ORDER BY
的 3 OR
条件这么慢?
您可以尝试扩展 OR
(来自 Oracle,但思路相同):
OR expansion is a transformation that can be used to optimize disjunctive queries (queries that contain OR clauses).
The basic idea in OR expansion is to transform a query containing disjunctions into the form of a UNION ALL query of two or more branches. This is done by splitting the disjunction into its components and associating each component with a branch of a UNION ALL query.
WITH cte AS (
SELECT *
FROM Car
WHERE ModelId = 642 AND RegionId IN (23,63,1,30,5,6,7,9,15)
UNION ALL
SELECT *
FROM Car
WHERE ModelId = 242 AND RegionId IN (23,63,1,30,5,6,7,9,15,26)
UNION ALL
SELECT *
FROM car
WHERE ModelId = 334 AND RegionId IN (23,63,1,30,5,6,7,9,15,26)
)
SELECT TOP 30 *
FROM cte
ORDER BY id DESC;
可能更糟
SELECT TOP 30 a.*
FROM Car
WHERE (ModelId in (642, 242, 334) AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15))
OR (ModelId in (242, 334) AND RegionId = 26)
ORDER BY Id DESC
我的查询:
SELECT TOP 30 a.*
FROM Car
WHERE (ModelId = 642 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15)) OR
(ModelId = 242 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15, 26)) OR
(ModelId = 334 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15, 26))
ORDER BY Id DESC
它在 30 秒内执行。
如果我删除 order by Id
部分,它会在 1 秒内执行。
或者如果我删除一个 OR
条件,它也会在 1 秒内执行。
WHERE (ModelId = 642 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15)) OR
(ModelId = 242 AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15, 26))
ORDER BY Id DESC
列 ModelId
和 RegionId
有索引。 Id
是主键。
执行计划显示 97% 的聚簇索引搜索了 Id。
请帮帮我。为什么 ORDER BY
的 3 OR
条件这么慢?
您可以尝试扩展 OR
(来自 Oracle,但思路相同):
OR expansion is a transformation that can be used to optimize disjunctive queries (queries that contain OR clauses).
The basic idea in OR expansion is to transform a query containing disjunctions into the form of a UNION ALL query of two or more branches. This is done by splitting the disjunction into its components and associating each component with a branch of a UNION ALL query.
WITH cte AS (
SELECT *
FROM Car
WHERE ModelId = 642 AND RegionId IN (23,63,1,30,5,6,7,9,15)
UNION ALL
SELECT *
FROM Car
WHERE ModelId = 242 AND RegionId IN (23,63,1,30,5,6,7,9,15,26)
UNION ALL
SELECT *
FROM car
WHERE ModelId = 334 AND RegionId IN (23,63,1,30,5,6,7,9,15,26)
)
SELECT TOP 30 *
FROM cte
ORDER BY id DESC;
可能更糟
SELECT TOP 30 a.*
FROM Car
WHERE (ModelId in (642, 242, 334) AND RegionId IN (23, 63, 1, 30, 5, 6, 7, 9, 15))
OR (ModelId in (242, 334) AND RegionId = 26)
ORDER BY Id DESC