首页 文章

主键是否可以是群集表上的非群集索引?

提问于
浏览
0

我正在设计一个会员表来存储网站的用户 . 它将在用户每次登录网站时使用,并偶尔访问以更新用户详细信息 .

用户将使用电子邮件地址和密码登录,并且每个帐户都将拥有唯一的电子邮件地址 . 因此,成员表的Email列应该是聚簇索引似乎是合乎逻辑的,因为当用户登录时,此表上的大多数查询都将针对Email列 . 使电子邮件列唯一且聚簇索引的关键应该在用户快速登录并提高性能时查询用户的数据 .

但据我了解,将电子邮件列设置为主键有两个原因是错误的 . 一,主键应该是不变的,所以如果用户决定更改他们的电子邮件地址,那么所有外键都必须更新,这将是不好的 . 其次,电子邮件地址是字符串,使得连接速度比PK为int时慢 .

那么我可以将非聚集索引作为主键吗?因此,该表既有一个带有电子邮件的聚簇索引作为它的唯一键,又有一个int主键作为非聚簇索引?

谢谢,邓肯

3 回答

  • 4

    主键是逻辑数据库设计,只需要是唯一且非NULL(使用索引实现) .

    此外,您可以选择单个聚簇索引,该索引应该是窄的,唯一的,增加的和静态的(电子邮件可能对此不利) .

    我会在其上创建一个IDENTITY int主键和簇 .

    我会在电子邮件中添加一个唯一的非聚集索引并“包含”其他列,以便最常见的重度查询覆盖(即密码哈希) . 请注意,您不需要将聚簇键添加到包含的列中,因为它始终作为非聚集索引中的书签包含在内 .

    查看执行计划以确保您没有在用户表中看到任何表扫描或聚簇索引扫描 .

    我想补充一点,通常人们认为查看查询使用聚簇索引是一件好事 . 我认为在索引覆盖的查询中使用的非聚集索引扫描或搜索在聚簇索引(没有聚簇索引的表)上与聚簇索引一样好,并且优于聚簇索引扫描或搜索 . 我还认为聚集索引是一个引导人们对事物进行各种假设的名称(首先,它不是表上的索引,它表明表完全存储在索引结构中)和误解关于它的重要性 . 在非常大的操作中,聚簇索引是最重要的,其中按照聚类的顺序需要大量数据 .

    典型OLTP查询的实际(读取)查询速度来自于在查询中的所有表上使用最窄的非聚集索引覆盖查询,每个列都按照适当的顺序排列,并为查询/参数指定正确的排序方向 .

  • 3

    您绝对可以在主键中创建非聚集索引 .

    但是,我认为你有点倒退了 . 电子邮件地址将成为一个特别糟糕的聚集索引,因为它本身并不是有序的 . 随着表的增长,由于页面拆分,重新排序等原因,您将失去性能.2958157_

    正如@Cade Roux所说,我会将autonum作为聚集索引,在电子邮件地址上强制执行唯一性 .

    EDIT: 聚簇索引表示数据在磁盘上的物理存储方式 . 非顺序聚簇索引会损害性能,因为必须重新排序数据(导致页面拆分) . 对于扫描用户表中的单行,您可能会发现聚簇索引和非聚簇索引之间的差异可以忽略不计 . 但是,根据@gbn发布的优秀链接,您可能会在范围选择上获得更好的性能,因为数据是连续的 . 尽管如此,我个人必须真正思考为聚簇索引使用字符串(或任何固有的无序数据)的决定 .

    EDIT2: 我能想到的一个例外情况是,如果你通常按字母顺序选择电子邮件地址的用户...你仍然会有更慢的 INSERT 但你应该能够更快地检索这些分组...作为@Cade Roux在评论中表示:由于聚集索引,你应该 not 期望单行 SELECT 更具性能 .

  • 2

    是的你可以 . 什么时候你创建表,设置如下列:

    CREATE TABLE Members
    (
      ID INT NOT NULL IDENTITY(10000,1),
      Email Varchar(200) NOT NULL CONSTRAINT pk_Members PRIMARY KEY NONCLUSTERED,
      Otherstuff ...
    )
    
    CREATE CLUSTERED INDEX cdx_Members ON Members(ID)
    

相关问题