非聚集外键索引建议

时间:2013-08-02 18:27:36

标签: sql-server indexing foreign-keys sql-server-2012

我的数据库中有几个表是父子关系。例如:

CREATE TABLE [dbo].[cntnr_header] 
(
    [cntnr_id]            [dbo].[uid]     NOT NULL,
    CONSTRAINT [pk_cntnr_header] PRIMARY KEY CLUSTERED ([cntnr_id] ASC),
);

CREATE TABLE [dbo].[cntnr_content] 
(
    [cntnr_content_id]  [dbo].[uid]       NOT NULL,
    [cntnr_id]          [dbo].[uid]       NOT NULL,
    CONSTRAINT [pk_cntnr_content] 
       PRIMARY KEY CLUSTERED ([cntnr_content_id] ASC),
    CONSTRAINT [fk_cntnr_content_cntnr_header] 
       FOREIGN KEY ([cntnr_id]) 
       REFERENCES [dbo].[cntnr_header] ([cntnr_id]),
);

目前您可以看到表cntnr_id中的外键cntnr_content上没有索引。我运行了调优向导,实际上我看到它建议在表cntnr_content_id上为cntnr_idcntnr_content添加非聚集索引。我真的不明白这一点,因为cntnr_content_id已经是一个聚集索引。为什么会推荐像这样的索引?

CREATE NONCLUSTERED INDEX [_dta_index_cntnr_content_7_821577965__K1_K2] ON [dbo].[cntnr_content]
(
    [cntnr_content_id] ASC,
    [cntnr_id] ASC
)WITH (SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF) ON [PRIMARY]

我认为我可能应该在此表的cntnr_id上添加一个非聚集索引。

这种情况是否有推荐做法?我应该总是添加这样的关系的某些索引吗?

许多查询要么在cntnr_id上将这两个表连接在一起,要么通过指定cntnr_contentcntnr_id上进行选择。这也是一个更新/删除重表。更新和删除始终在主键(cntnr_content_id)上完成。

2 个答案:

答案 0 :(得分:4)

聚簇索引作为二叉树物理存储在磁盘上。通常,它们非常适合读取繁重的工作负载。

分析器建议您不在cntnr_content表上使用非聚集索引的原因是因为您通常会使用外键访问该表上的数据。

在这种情况下,主键上的聚簇索引无用,因为数据以使用外键时很难找到的方式分布在磁盘上。这就是它建议使用非聚集索引的原因。

更改为非聚簇索引允许数据库选择磁盘格式,这种格式对于通过外键进行查找更为理想。当然,这样做会影响主键查找的速度,所以这是一个权衡 - 在一种情况下你会获得更快的速度,但在另一种情况下会牺牲一些速度。

答案 1 :(得分:0)

cntnr_id上的非聚集索引显然对于外键,因此如果您尝试从头表中删除一个,则不需要进行表扫描。

同样适用于您通过标题查找的主要用例。

在cntnr_content_id上单独拥有一个非聚集索引真的没有多大意义。两者(cntnr_id,cntnr_content_id)上的复合非聚集索引(按此顺序)可能有意义,如果它覆盖,因为它将比聚簇索引更窄。