SQL Server-是否需要将具有唯一约束的索引作为列之一?

时间:2019-01-15 07:19:15

标签: sql sql-server indexing

我有以下查询:

SELECT PrimaryKey
FROM dbo.SLA
WHERE SLAName = @input
AND FK_SLA_Process = @input2
AND IsActive = 1

这是该 SLA 表的索引。

CREATE INDEX IX_SLA_SLAName_FK_SLA_Process_IsActive ON dbo.SLA (SLAName, FK_SLA_Process, IsActive) INCLUDE (SLATimeInSeconds)

但是, SLAName 列是唯一的,因此具有唯一的约束/索引。 我创建的索引是否过大?我还是需要它还是SQL Server将使用在唯一列 SLAName 上创建的索引?

3 个答案:

答案 0 :(得分:2)

如果您的索引仅位于SLAName上,那将是一个“过大杀手”,但同时您也按FK_SLA_ProcessIsActive进行排序,因此需要需求列的查询将从中受益更多您的索引,如果只有唯一索引,则更少。

对于这样的查询:

SELECT PrimaryKey
FROM dbo.SLA
WHERE SLAName = 'SomeName'

两个索引都将产生相同的结果,您的索引将毫无意义。但是对于类似这样的查询:

SELECT PrimaryKey
FROM dbo.SLA
WHERE SLAName = 'SomeName'
AND FK_SLA_Process = 'Some Value'

SELECT SLATimeInSeconds
FROM dbo.SLA
WHERE SLAName = 'SomeName'

您的索引将比唯一索引更好(第二个示例是覆盖索引)。

您应该检查对该表执行哪种SELECT并确定是否需要此表。请记住,拥有许多索引可能会加快选择速度,但会降低插入,更新和删除的速度。

答案 1 :(得分:1)

假设您有这样的表声明:

CREATE TABLE SLA
(
   ID  INT PRIMARY KEY,
   SLAName VARCHAR(50) NOT NULL UNIQUE,
   fk_SLA INT,
   IsActive TINYINT
)

内部有两个索引:

CREATE TABLE [dbo].[SLA](
    [ID] [int] NOT NULL,
    [SLAName] [varchar](50) NOT NULL,
    [fk_SLA] [int] NULL,
    [IsActive] [tinyint] NULL,
PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
UNIQUE NONCLUSTERED 
(
    [SLAName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

因此此查询将具有索引查找并具有最佳计划:

SELECT s.ID 
FROM dbo.SLA s 
WHERE s.SLAName = 'test'

它的查询计划指示索引查找,因为我们正在按索引UNIQUE NONCLUSTERED ([SLAName] ASC )进行搜索,并且不使用WHERE语句中的其他列:

enter image description here

但是,如果您向WHERE中添加了额外的参数:

SELECT s.ID 
FROM dbo.SLA s 
WHERE s.SLAName = 'test'
AND s.fk_SLA = 1
AND s.IsActive = 1

执行计划会额外查找:

enter image description here

当索引没有必要的信息时,将发生查找。 SQL查询引擎必须从UNIQUE NONCLUSTERED索引数据结构中找出表fk_SLA中列IsActiveSLA的数据。

因此,与拥有UNIQUE NONCLUSTERED索引一样,您的索引是过大的:

UNIQUE NONCLUSTERED 
(
    [SLAName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
     ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

答案 2 :(得分:0)

如果SLAName列为unique且具有unique constraint,则任何仅返回一或0行的查询(所有查询均带有点搜索包含SLAName = 'SomeName'条件的关键字)将使用unique index并在基表中最多设置一个lookup

除非您的查询具有SLAName like 'SomeName%'之类的范围搜索,否则无需覆盖索引,因为索引搜索+ 1查找与仅索引搜索几乎相同,也不需要浪费空间/维持另一个索引来获得如此可怜的性能提升。