Phi*_*ler 3 index sql-server-2008 sql-server
我有一个相对较大的表,它以一种方式访问,正好通过一个查询(在读取端)。
查询按两列(均为bit
)过滤表,并按第三列(整数)排序。请注意,查询命名列(它实际上不使用“*”)。“TOP 1000”是有意的,是生产查询的一部分:
生成了查询——不知道为什么它会以这种方式生成。
SELECT TOP 1000
*
FROM
MyTable m
WHERE
m.IsFlag1 != 1
AND m.IsFlag2 != 1
ORDER BY
m.SomeId
Run Code Online (Sandbox Code Playgroud)
我有一个覆盖索引,主列是IsFlag1
和IsFlag2
。
执行计划显示并在此索引上查找索引,然后进行排序。根据执行计划,排序占查询成本的 97%。
我尝试添加SomeId
为索引的主列(第三列),但执行计划保持不变。
然后我尝试添加一个仅使用 SomeId 作为主列的覆盖索引,保留原始索引。执行计划然后对新查询进行索引扫描,操作成本显着降低(并且在功能上更快)。
说了这么多,我想尽可能地优化这个查询。有没有办法修改索引,以便它简单地进行查找?
一般来说,不可能在条件x <> 1
和上使用索引查找y <> 1
。
使用x,y
最好的索引,您可以将其转换为两个范围搜索(x < 1
和x > 1
),并 带有剩余谓词y <> 1
(并且这将无法使用额外的索引键列来避免排序)
对于一bit
列,因为它只能有三个值。0
, 1
,NULL
逻辑上WHERE bit_column <> 1
等同于 WHERE bit_column = 0
但似乎 SQL Server 没有利用这里的优势并为您转换<>
为=
条件。
添加几个检查约束可以完成这项工作,尽管这些显然是多余的,因为它们实际上并没有以任何方式限制数据类型的允许值(因为NULL
如果检查约束UNKNOWN
计算为通过)
CREATE TABLE MyTable
(
Foo INT,
IsFlag1 BIT NULL CHECK (IsFlag1 IN (0, 1)),
IsFlag2 BIT NULL CHECK (IsFlag2 IN (0, 1)),
SomeId INT
);
CREATE NONCLUSTERED INDEX ix
ON MyTable(IsFlag1, IsFlag2, SomeId)
INCLUDE (Foo);
Run Code Online (Sandbox Code Playgroud)
该计划现在确实显示了寻求 IsFlag1 = 0 AND IsFlag2 = 0
或者,这个过滤索引也避免了需要一个 SORT
CREATE NONCLUSTERED INDEX ix
ON MyTable(SomeId)
INCLUDE (Foo,IsFlag1, IsFlag2)
WHERE IsFlag1 != 1 and IsFlag2 != 1
Run Code Online (Sandbox Code Playgroud)
它对筛选的索引(按 排序的合格行SomeId
)进行TOP
扫描,并在检索到 1,000 行后停止扫描。在索引IsFlag1, IsFlag2
中使用INCLUDE
-d 以避免在没有这个的情况下发生不必要的查找。
归档时间: |
|
查看次数: |
193 次 |
最近记录: |