假设我有一个包含 1000 条记录的表,并且我有以下查询,它将返回 7 条记录:
SELECT *
FROM MyTable
WHERE IndexedColumn > 5000
AND OtherIndexedColumn = 2
Run Code Online (Sandbox Code Playgroud)
由于这两列都有最新的索引,SQL Server 可以做出假设并更快地找到值,并且两个查询都是 SARGable(理想情况下读取次数更少)。但是,假设我需要确保该值不等于另一个值,假设不同的列是 12,所以我必须添加
AND AnotherIndexedColumn <> 12
Run Code Online (Sandbox Code Playgroud)
如果那是WHERE
子句中的最后一条语句,SQL Server是否使用前两个WHERE语句中的SARGability来先过滤,得到7行,然后查看7行中的每一行是否不等于12,或者是否适用在<>
对原始数据集的1000行的每一行?
我问的原因是因为我知道我可以使用子查询或 CTE 来执行 SARGable 过滤器的第一部分,然后在 7 行中,查看每行是否不相等,但查询是优化器已经在幕后这样做了,还是最好自己做?
Aar*_*and 13
理论上,尤其是在现代版本的 SQL Server 中,WHERE 子句的顺序完全没有区别。SQL Server通常会以最有效的顺序处理过滤器,并会选择它确定的索引以进行最有效的查询。当 WHERE 子句包含 JOIN 条件或将过滤器应用于外部连接的列时,可能会出现一个差异;当使用 FORCE ORDER 或特定跟踪标志等选项时,其他差异可能会发挥作用。
重写为 CTE 以“强制”SQL Server 首先处理 CTE 内的过滤器是行不通的 - SQL Server 无论如何都会重新编写它,并按照它认为最好的顺序处理它。这就是为什么,例如,您无法通过使用 CTE 或子查询首先过滤掉坏数据来避免无效转换错误 - SQL Server 可能仍会在任何过滤器执行任何操作之前将坏数据呈现给转换。
(Erland 在Connect #537419 中抱怨了这一点。)
所以,再一次,一般来说,不要重新编写 SQL 代码来试图超越优化器或阻止它做一些愚蠢的事情。在某些情况下,它可以选择可能通过更改查询本身来解决的错误索引,但是在您已经相信优化器选择了错误索引的情况下处理那些索引(并且在解决这些问题之前,消除更可能的原因,如参数嗅探、不良统计数据等)。
归档时间: |
|
查看次数: |
741 次 |
最近记录: |