SQL Server 为一列创建多个非聚集索引与在一个索引中创建多个列

Posted

技术标签:

【中文标题】SQL Server 为一列创建多个非聚集索引与在一个索引中创建多个列【英文标题】:SQL Server creating multiple nonclustered indexes for one column vs having multiple columns in just one index 【发布时间】:2012-12-11 20:06:32 【问题描述】:

假设我有下表

UserID(身份)PK UserName - 唯一非空 UserEmail - 唯一非空

推荐什么以获得最佳性能?

分别为UserNameUserEmail 创建非聚集索引

只有一个,包括两列

请分享你的想法为什么一个比另一个更可取。

【问题讨论】:

【参考方案1】:

另一个需要考虑的重点是:复合索引(由多列组成)仅在最左侧的 n 列被引用时才会使用(例如在 WHERE 子句中)。

所以如果你有一个单一的复合索引

(UserID, UserName, UserEmail)

那么这个索引可能用在以下场景:

当您单独搜索 UserID 时(仅使用最左侧的 1 列 - UserID) 当您搜索 UserIDUserName(使用最左侧的 2 列)时 当您搜索所有三列时

但是这个单一的复合索引将永远能够用于搜索

只是UserName - 它是索引中的第二列,因此该索引不能永远被使用 只是UserEmail - 它是索引中的第三列,因此该索引不能永远被使用

请记住这一点 - 仅仅因为一列是索引的一部分并不一定意味着该索引将支持和加速单独在该单列上的搜索!

因此,如果您的使用模式和应用程序确实需要单独搜索 UserName 和/或 UserEmail(不提供其他搜索值),那么您必须在这些列上创建单独的索引- 仅使用一种化合物不会有任何好处。

【讨论】:

【参考方案2】:

定义索引的最佳方式完全取决于您将如何使用该表。仅通过查看表定义来选择索引是不明智的。

如果您的代码使用用户名搜索您的表或通过用户名将您的表与另一个表连接起来,那么在该列上定义一个索引是明智的。如果您的代码使用两列(用户名和用户邮件)将表与另一个表连接起来,那么为这两列定义索引是明智的。由于您的所有列都被定义为唯一的,我几乎不相信会出现这种情况,因此您不需要该表上的多个列索引。

关于使用多列索引可能还有一些额外的建议:多列索引也用于部分适合索引但有条件的过滤器。 例子: 如果您在用户名和用户邮件上定义一个两列索引(按给定顺序),您将在通过两列(用户名和用户邮件)过滤的搜索中获得性能提升。使用该索引,您还将在仅使用用户名的过滤器中获得性能提升,因为这是索引的第一列,但在通过 usermail 进行搜索时却没有,这是因为不能单独使用索引的第二列。 规则是:索引可用于过滤完全匹配的列或过滤与索引定义中后续顶部列匹配的列子集。

【讨论】:

【参考方案3】:

请分享你的想法为什么一个比另一个更可取。

这取决于你做什么。

看,索引只能“从左到右”使用。因此,用户 ID 上的索引;如果我选择仅按用户名过滤,用户名将毫无用处。

一般来说,我会在这里假设三个索引:

Uniuqe 索引,聚集在 UserID 中,作为主键。 用户名的唯一索引,非集群。 UserEMail 上的唯一索引,非集群。

原因完全不是为了性能,而是:

您需要第一个作为外键关系的主键。 您需要另外两个来正确处理唯一约束 - 没有索引就无法做到这一点。

此外,您需要灵活地通过 UserName 和 UserEMail 进行搜索,这意味着不能仅将它们组合在一起。

性能确实排在最后——出于性能原因,所有这些索引都可能包含所有附加字段(不是作为索引的一部分,而是作为包含的列。但实际上,没有其他明智的方法可以让这个表工作,除非你允许同一用户多次注册。

【讨论】:

以上是关于SQL Server 为一列创建多个非聚集索引与在一个索引中创建多个列的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server的聚集索引和非聚集索引

SQL Server索引的作用

SQL SERVER数据库 唯一索引 非唯一索引 聚集索引 非聚集索引 之间区别

SQL Server 2016新特性:列存储索引新特性

SQL Server查询优化和事务处理

聚集和非聚集索引 - SQL Server 和 Oracle?