两列上的 SQL 索引

Posted

技术标签:

【中文标题】两列上的 SQL 索引【英文标题】:SQL Index on two columns 【发布时间】:2011-08-31 22:52:10 【问题描述】:

这是我的简单场景:

我有一个用户表和一个位置表。 ONE User 可以与 MANY Locations 相关,所以我有一个 UserLocation 表,如下所示:

ID (int-Auto Increment) PK
UserID (Int FK to the Users table)
LocID (Int FK to the Locations table)

现在,由于 ID 是 PK,因此默认情况下它在 SQL-Server 中被索引。我对其他两列有点困惑:

OPT 1: 我在两列上都定义了一个索引,例如: IX_UserLocation_UserID_LocID

OPT 2: 我定义了两个单独的索引,例如:IX_UserLocation_UserID & IX_UserLocation_LocID

如果两者都做同样的事情,请原谅我 - 在这种情况下请解释一下。如果不是 - 哪个更好,为什么?

【问题讨论】:

您真的需要联结表中的自动递增代理id 字段吗?它有什么用?我会在 2 个 FK 列上创建一个复合主键。将针对该表运行哪些查询?他们会通过userlocation 还是两者都查找? 谢谢你们。仅供参考 - ID 列是我们的传统,我们将它保存在所有表中,在大多数地方它用于唯一记录标识符的目的。我知道这里 UserID + LocID 可以是一个复合 PK,但为了简化和标准化,我们保留了 ID 字段。如果这不令人信服 - 现在忘记 ID 密钥! 【参考方案1】:

你需要

2 列 UserID(Int FK 到用户表) Lo​​cID(Int FK 到 Locations 表) 两个(UserID, LocID) 上的一个PK 反面的另一个索引(LocID, UserID)

您可能不需要两个索引,但这种情况很少见

编辑,一些指向其他 SO 答案的链接

SQL: Do you need an auto-incremental primary key for Many-Many tables? SQL - many-to-many table primary key Difference between 2 indexes with columns defined in reverse order

【讨论】:

【参考方案2】:

我们租用数据库的目的有几个。一种是快速信息检索,另一种是声明性引用完整性(DRI)。

如果您的要求是用户只能与给定位置关联一次,那么您需要一个关于 UserID 和 LocatonID 的唯一索引。

如果您的问题是如何快速检索数据,答案是 - 视情况而定。您如何访问数据?如果您总是获得用户的整个位置集,那么我可能会在 UserID 上使用聚集的非唯一索引。如果您的访问权限是“谁在位置 x?”那么您可能需要在 LocationID 上创建一个聚集的非唯一索引。

如果您同时提出这两个问题,您可能需要两个索引(尽管您只获得 1 个聚集的索引,因此第二个索引可能需要使用 INCLUDE 来获取另一列)。

无论哪种方式,您都可能不希望 ID 作为您的聚集索引(在 SSMS 表设计器中将列标记为 PK 时的默认设置)。

HTH, -埃里克

【讨论】:

【参考方案3】:

除了“gbn”答案。这将取决于 Where 子句。无论您是使用用户还是位置或两者都使用

【讨论】:

【参考方案4】:

您可能应该创建两个单独的索引。外键经常忘记的一件事是删除用户可能会级联删除表中的用户位置关系。如果用户 ID 上没有索引,这可能会导致您的用户位置关系的表锁定。这同样适用于删除位置。

【讨论】:

是否有 2 个单独的索引涵盖 UserID 和 LocID 的任何 where 子句组合。性能有什么区别吗?【参考方案5】:

在 dev 上设置您认为需要的所有索引并检查您的应用运行的查询的 query plans 并查看读取了哪些索引的最佳方法。

【讨论】:

以上是关于两列上的 SQL 索引的主要内容,如果未能解决你的问题,请参考以下文章

在两列上创建索引以检查日期是不是介于这两个列之间

为啥 SQL Server 不使用计算列上的索引?

如何在日期时间索引和两列上合并熊猫数据框

SQL Server 2008 在具有空间索引的可空地理列上的性能

sql server 2005 一个索引多个字段,字段的排列顺序对搜索有啥影响??

我应该摆脱 Guid 列上的聚集索引吗