没有字段的非聚集索引的用途是什么?

时间:2019-02-25 08:35:27

标签: sql-server indexing sql-server-2008-r2

我最近开始维护的旧版应用程序的数据库有2个索引,它们的范围我不了解。

在其上创建索引的表是这样的(它是存储SW对象之间的链接的表(例如,它允许链接一个Customer和2个Order,因此建立了Customer和2个Order之间的关系) ):

CREATE TABLE [LINKS](
    [LINK_ID] [int] NOT NULL, -- Counter Primary Key
    [LINK_TYPE] [int] NOT NULL,-- Foreign Key to "link types" table
    [ID_LINK_FROM] [int] NOT NULL, -- this is not FK, just an int
    [ID_LINK_TO] [int] NOT NULL, -- this is not FK, just an int
    [ID_LINK_TO_DETAIL] [int] NULL, -- this is not FK, just an int
    [HAS_PRIORITY] [nchar](1) NOT NULL -- this is 'Y'/'N' "Boolean-like"
)

该表具有一个计数器PK和三个实际上缺少FK的整数字段,因为目标取决于LINK_TYPE是另一个表。 当然,完整的解决方案将是数据库规范化,但这不是现在的选择。

此表在JOIN中使用它的所有查询中都明确介绍了性能问题。为了解决这个问题,过去有人创建了2个(从我的角度来看这是没有用的)索引:

CREATE NONCLUSTERED INDEX [IDX_LINKS_ID_LINK_FROM] ON [dbo].[LINKS]
(
    [ID_LINK_FROM] ASC
)

CREATE NONCLUSTERED INDEX [IDX_LINKS_ID_LINK_TO] ON [dbo].[LINKS]
(
    [ID_LINK_TO] ASC
)

那些索引仅包含“缺少FK”,因此它们无用,因为肯定将丢失的FK用于JOIN,但是索引中缺少任何其他字段。

所以我的“逆向工程”问题是:您确定这两个索引没有用吗?

据我所知,由于缺少数据库规范化,以下2个将是更好的“补丁”:

CREATE NONCLUSTERED INDEX [IDX_LINKS_ID_LINK_FROM] ON [dbo].[LINKS]
(
    [ID_LINK_FROM] ASC
)
INCLUDE ( LINK_TYPE,
ID_LINK_TO,
ID_LINK_TO_DETAIL,
HAS_PRIORITY)

CREATE NONCLUSTERED INDEX [IDX_LINKS_ID_LINK_TO] ON [dbo].[LINKS]
(
    [ID_LINK_TO] ASC
)
INCLUDE ( LINK_TYPE,
ID_LINK_FROM,
ID_LINK_TO_DETAIL,
HAS_PRIORITY)

至少最后2个索引包含查询中可能需要的所有字段,因此它们要好得多。

能否请您确认我在正确的路径上?

从最初的测量中,我对一些“重要查询”进行了改进,但是在继续这条道路之前,我希望获得一些反馈。

2 个答案:

答案 0 :(得分:2)

索引的用途比 just “覆盖”索引更多,这就是您建议的索引。

优化器可能仍然认为,在窄索引上进行索引查找/扫描,然后在聚集索引中进行书签查找比表扫描更有效。有时(但并非总是如此)做出决定是正确的。

请记住,INCLUDE在SQL Server 2008之前不存在。非聚集索引的日期要早于此。

与所有索引决定一样,只有您才能在正确的位置上确定对您的数据的所有查询/修改模式,并且能够测试对索引的建议更改。确保您始终对代表性的查询样本进行分析,而不仅仅是您认为会因特定索引更改而特别加速的查询样本。


如果可以帮助您解决问题,请使用类比的书。想象一下关于某个主题的教科书。该书将由子主题编入各章,而这些章将遵循一定的逻辑顺序。本书前面的目录将告诉您处理子主题的顺序,如果您清楚需要了解哪个子主题,则可以跳至感兴趣的章节。

主要书籍内容(叶子)+目录(非叶子)构成聚集索引。

但是这本书也可能有一个或更多实际索引,通常位于书的背面。这些功能可让您执行按关键字等狭义进行的搜索,并告诉您要转到该书的哪一页提到哪个关键字。您仍然必须转到本书的主要内容以获得所需的信息。

书籍索引=非丛集索引。索引中的定位关键字=索引查找/扫描。在内容中引用页面=书签查找。

带有INCLUDE列的非聚簇索引对于这个类推有点棘手,但是图片例如可以将几个术语组合在一起的“词汇表”,更详细地扩展其定义,并具有“另请参见”引用,这些引用再次引用了本书内容中的页面。

答案 1 :(得分:1)

使用查询,我通常使用它来查询表的索引是否有用。用您当前的索引,然后用新的索引检查它:

SELECT i.name, s.*
FROM sys.dm_db_index_usage_stats s
    JOIN sys.indexes i ON i.object_id = s.object_id
        AND i.index_id = s.index_id
    JOIN sys.sysindexes si ON si.id = i.object_id
        AND si.indid = i.index_id
WHERE s.object_id = OBJECT_ID('LINKS')
ORDER BY i.name