由于一个简单的 IN 语句,大量的全表扫描(大约 600 次)
Posted
技术标签:
【中文标题】由于一个简单的 IN 语句,大量的全表扫描(大约 600 次)【英文标题】:Lot of full table scans (around 600) because of a simple IN statement 【发布时间】:2015-06-23 11:22:26 【问题描述】:我的查询中有 2 个 CTE。在查询结束时,我只需加入它们并将结果写入页面。
在页面上我有过滤器选项,所以当我有过滤器时,我必须在查询末尾添加一个简单的 IN 语句。
当我没有 where 条件时,查询速度足够快(大约 5 秒)以获得超过 5 k 的结果。
但是当我有琐碎的 where 条件时,查询大约需要 3-4 分钟,这很奇怪。
所以我在 SQL MS 中对其进行了分析,并检查了实际的执行计划。我意识到,如果没有 where 条件,我只有一次全表扫描,但 where 条件围绕结果的数量。
之后,我简单地将查询放入内联表 ()x 中,并在其外部使用 where 条件,结果约为 1 秒。
见下面的三个查询。 你能描述一下为什么会发生这种情况以及如何防止这种情况发生吗?
/* 大约需要 5 秒 6k 结果*/ WITH First_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5) 作为 ( …… ) WITH Second_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5) 作为 ( …… ) 选择 * FROM First_CTE AS t1 左连接 Second_CTE AS t2 ON t1.COLUMN2 = t2.COLUMN2 /* 大约需要 4 分钟 600 结果*/ WITH First_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5) 作为 ( …… ) WITH Second_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5) 作为 ( …… ) 选择 * FROM First_CTE AS t1 左连接 Second_CTE AS t2 ON t1.COLUMN2 = t2.COLUMN2 WHERE t2.SomeColumn IN ( 22,23,24) -- 2 或更多值 /* 大约需要 1 秒 600 结果 */ WITH First_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5) 作为 ( …… ) WITH Second_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5) 作为 ( …… ) 选择 * 从 ( 选择 * FROM First_CTE AS t1 左连接 Second_CTE AS t2 ON t1.COLUMN2 = t2.COLUMN2 )X WHERE x.SomeColumn IN ( 22,23,24) -- 2 或更多值【问题讨论】:
查询计划显示什么?如果将WHERE
条件向上移动到合适的 CTE 一半会发生什么?
【参考方案1】:
CTE 只是语法(它没有具体化) 可以肯定的是,缓慢的 IN 创建了一个循环,在该循环中多次评估 CTE
在 1 秒内运行的最后一个最像每个 CTE 被评估一次,然后将 where 应用于结果
您确实知道 t2.SomeColumn IN (22,23,24) 否定了左边 你不妨使用一个连接
试试这个
SELECT *
FROM First_CTE AS t1
JOIN Second_CTE AS t2
ON t1.COLUMN2 = t2.COLUMN2
AND t2.SomeColumn IN ( 22,23,24) -- 2 or more value
最好将 t2.SomeColumn IN (22,23,24) 向上移动到 CTE 中,以使查询优化器变得更加愚蠢
WITH First_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5)
AS
(
....
)
WITH Second_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5)
AS
(
....
WHERE SomeColumn IN ( 22,23,24)
)
SELECT *
FROM First_CTE AS t1
JOIN Second_CTE AS t2
ON t1.COLUMN2 = t2.COLUMN2
【讨论】:
【参考方案2】:你可以试试这个,看看它是否有所作为?
WITH First_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5)
AS
(
....
)
WITH Second_CTE(ID,COLUMN2,COLUMN3,COLUMN4,COLUMN5)
AS
(
....
)
SELECT *
FROM First_CTE AS t1
LEFT JOIN Second_CTE AS t2 ON t1.COLUMN2 = t2.COLUMN2
AND t2.SomeColumn IN ( 22,23,24) -- 2 or more value
【讨论】:
这是执行计划为 4 分钟的查询。我看不出您的查询与我的第二个示例之间的区别。我错过了什么吗? 我将条件移至JOIN
并删除了WHERE
子句
啊我现在看到了,但是结果不一样,你知道的,因为左连接。
@LóriNóda 结果不同,因为现在它实际上是左连接。 where 中的那些条件将其变成了常规连接。以上是关于由于一个简单的 IN 语句,大量的全表扫描(大约 600 次)的主要内容,如果未能解决你的问题,请参考以下文章