例如,这里有FOO
表上的2个索引:
ALTER TABLE [dbo].[FOO]
ADD CONSTRAINT [PK_FOO] PRIMARY KEY CLUSTERED ([id] ASC)
CREATE NONCLUSTERED INDEX [IX_FOO]
ON [dbo].[FOO] ([id] ASC, [a] ASC, [b] ASC)
使用IX_FOO
列进行过滤时,许多查询都在使用a
。 id
中的IX_FOO
列似乎是多余的,因为PK_FOO
正在索引它。因此,我想要从id
中删除IX_FOO
列,如下所示:
CREATE NONCLUSTERED INDEX [IX_FOO2]
ON [dbo].[FOO] ([a] ASC, [b] ASC)
INCLUDE ([id])
但我不确定自己。索引是否需要包含PK列?
答案 0 :(得分:2)
不,不。非聚簇索引将指向主表的主键,因此无需将其(主键)添加到任何非聚簇索引。
换句话说,所有非聚簇索引都隐式包含表的聚簇索引。
答案 1 :(得分:2)
索引中列的顺序很重要。
(ID, a, b)
上的索引与(a, b) include (id)
上的索引非常不同。
搜索时可以使用(ID, a, b)
上的第一个索引:
WHERE ID = 1 AND a = 2 AND b = 3
WHERE ID = 1 AND a = 2 AND b > 3 AND b < 5
WHERE ID = 1 AND a = 2
WHERE ID = 1 AND a > 2 AND a < 5
WHERE ID = 1
WHERE ID > 1 AND ID < 5
在仅搜索a
或仅搜索b
时,不将使用此索引:WHERE a = 2
; WHERE b = 3
。
所选列可以是ID
,a
,b
的任意组合 - 如果列数较多,则索引不够,引擎必须从表中读取它们。
搜索时可以使用(a, b) include (id)
上的第二个索引:
WHERE a = 2 AND b = 3
WHERE a = 2 AND b > 3 AND b < 5
WHERE a = 2
WHERE a > 2 AND a < 5
在仅搜索ID
或仅搜索b
时,不将使用此索引:WHERE ID = 1
; WHERE b = 3
。
所选列也可以是ID
,a
,b
的任意组合 - 如果有更多列,则索引不够,引擎必须从表中读取它们
如果ID
上存在聚簇索引,那么将ID
作为INCLUDE
添加到非聚集索引是没有意义的,因为聚簇列包含在每个非聚簇索引中隐含索引。这就是为什么通常建议使用窄聚簇索引,通常是4字节int
。聚集索引越宽,每个非聚集索引所需的空间就越多。
因此,(a, b) include (id)
上的索引与您案例中的(a, b)
相同。
我不确定引擎是否足够聪明,如果明确INCLUDE ID
,则不会浪费磁盘空间。这很容易检查。