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 次 |
| 最近记录: |