身份主键是否应始终为非群集?

时间:2017-06-17 21:40:08

标签: sql sql-server

假设一个表具有自动增量标识,例如:

CREATE TABLE [dbo].[Category]
(
    [CategoryId] INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [Title] NVARCHAR(50) NOT NULL,
    [Description] NVARCHAR(128) NULL
)

由于自动增量PK会使表本身排序,是否意味着我应该使CategoryId Non Clustered,然后在另外两列CREATE CLUSTERED INDEX [IX_Category_Column] ON [dbo].[JobCategory] ([Title], [Description])上创建聚簇索引?

3 个答案:

答案 0 :(得分:3)

默认情况下,

PRIMARY KEY会在该PK列上创建clustered index,而且我认为该索引存储了物理排序顺序,而不是IDENTITY列。< / p>

因此,如果需要,您应该在其余列上创建Non-clustered索引。

如果您打算在过滤条件或连接条件等中使用这些col,那么其他列上的索引肯定有助于提高查询性能。在这种情况下,它将执行索引扫描而不是表扫描。要体验相同的操作,请运行一个查询,该查询涉及这种情况下的其他列,有或没有索引。获取实际的查询执行计划并亲自查看。

答案 1 :(得分:1)

聚簇索引表示表中的所有数据都按照此索引进行排序。创建PrimaryKey时,您创建了Clustered Index。在每个表中只能有一个Clustered Index 因此,根据您将针对表运行的查询,根据需要在其他两列上创建非聚簇索引 另请注意,聚集索引应尽可能窄。原因是它包含在所有其他索引中。因此,当您在Title列上创建索引时,即使您没有指定它,它也将包含CategoryId列。

创建索引时,您还应考虑另一个方面。列可以是索引的一部分,也可以只是&#34;包含&#34;。这意味着它包含在索引中,但不使用此列对数据进行排序。当你想要索引中的列时,它不会在where子句或join中使用,但会输出你的查询。特别是当此列中的数据经常更改时。

让我们拿你的桌子并添加一些数据

insert into Category (Title, Description) values ('Title2', 'Description2_B')
insert into Category (Title, Description) values ('Title2', 'Description2_A')
insert into Category (Title, Description) values ('Title1', 'Description1_B')
insert into Category (Title, Description) values ('Title1', 'Description1_A')

现在在Title和Description列上创建索引

create nonclustered index idx_category_title on Category (title, Description)

在此表上运行select将为您提供

select Title, Description from category where title Like 'Title%'

Results:
    |  Title |    Description |
    |--------|----------------|
    | Title1 | Description1_A |
    | Title1 | Description1_B |
    | Title2 | Description2_A |
    | Title2 | Description2_B |

如您所见,结果按标题排序,然后按说明排序。使用此索引每次修改描述时,必须更新索引以对数据进行排序。

现在让我们尝试使用相同的表和相同的数据但是使用索引,其中列描述为&#34;包含&#34;

create nonclustered index idx_category_title on Category (title) include (Description)

在此设置上运行相同的选择将为您提供

select Title, Description from category where title Like 'Title%'

Results:
    |  Title |    Description |
    |--------|----------------|
    | Title1 | Description1_B |
    | Title1 | Description1_A |
    | Title2 | Description2_B |
    | Title2 | Description2_A |

如您所见,数据按标题排序,但不按说明排序。这里真正的性能提升是修改描述。由于索引未使用此列进行排序,因此更改索引不会更改索引中记录的位置。

答案 2 :(得分:1)

  

由于自动增量PK使表本身排序

事实并非如此。聚类键决定了行sorted when stored的方式。

通常,群集密钥应该很窄(例如intbigint)并且不断增加(例如identity())。

您还应该考虑为您的约束和索引提供更合理的名称,而不是接受sql server自动生成的任何名称。

create table dbo.Category (
    CategoryId int identity(1,1) not null
  , Title nvarchar(50) not null
  , Description nvarchar(128) null
  , constraint pk_Category_CategoryId primary key clustered (CategoryId)
);

支持以下查询:

select CategoryId, Title, Description 
from dbo.Category
where Title = 'MyTitle';

您将创建一个额外的非聚集索引,如下所示:

create nonclustered index ix_Category_Title 
  on dbo.Category (Title)
    include (Description);

参考: