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

问题描述 投票:2回答:2

我最近开始维护的遗留应用程序的DB有2个索引,其范围我不明白。

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

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"
)

该表有一个Counter 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个索引包含我在查询中可能需要的所有字段,因此它们要好得多。

你能否确认我走在正确的道路上?

从我对一些“重要问题”进行的第一次测量开始,我看到了一些改进,但我希望在继续这条道路之前得到一些反馈。

sql-server indexing sql-server-2008-r2
2个回答
2
投票

索引的用途多于“覆盖”索引,这是您提出的索引。

优化器可能仍然决定对窄索引进行索引搜索/扫描,然后在聚簇索引中进行书签查找比表扫描更有效。有时候(但绝不总是)正确地做出这个决定。

请记住,在SQL Server 2008之前,INCLUDE不存在。非聚集索引的日期远远超过它。

与所有索引决策一样,只有您才能确定数据的所有查询/修改模式,并能够测试建议的索引更改。确保您始终对代表性的查询示例进行概要分析,而不仅仅是您认为特定索引更改会特别加快的查询示例。


如果它有助于为您解决问题,请使用本书类比。想象一下关于某个主题的教科书。该书将由分科目安排到章节中,这些章节将遵循一些逻辑顺序。本书前面的目录将告诉您子主题的处理顺序,并允许您跳转到感兴趣的章节,如果您清楚需要了解哪个子主题。

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

但是这本书也可能有一个或多个实际索引,通常位于书的后面。这些将允许您执行一个狭窄的搜索,例如,通过关键字,并将告诉您哪个页面的书去哪个提到该关键字。您仍然需要转到本书的主要内容以获取所需的信息。

book indices =非聚集索引。在index = index seek / scan中定位关键字。引用内容中的页面=书签查找。

带有INCLUDE列的非聚集索引对于这种类比而言有点棘手,但是例如一个“术语表”,可以将几个术语组合在一起,更详细地扩展它们的定义,并且“参见”引用再次引用主要书籍内容中的页面。


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
© www.soinside.com 2019 - 2024. All rights reserved.