SQL Server 主键/聚集索引设计决策

6 database-design sql-server

寻找有关表/索引设计决策的一些建议,我必须对一些必须从现有的基于 4GL 的数据库移植到 SQL 服务器的表做出决定。

我有一个经常插入(从未更新)的产品历史记录表,并且该表具有这种结构

  1. 产品无字符串(20)
  2. 创建日期时间日期时间
  3. 描述字符串(100)

目前,主键由 ProductNo 和 CreatedDateTime 的组合组成,试图定义唯一的索引键。每个产品号我们可以有很多记录。

我将创建一些 1 对 1 相关表,并且不想将 productno 和 createddatetime 字段都携带到相关表中以充当外键。我也认为这种组合有点脆弱,以保证唯一性。

因此,我计划向表 'ProductHistoryPK' 添加一个新字段,作为递增的 Int 或 SequentialGuid 作为相关表的主键和外键。

在索引方面我正在考虑创建

  1. 新 ProductHistoryPK 字段上的非聚集主键。
  2. ProductNo 字段上的聚集索引,因为这是经常搜索的字段。

关于这个的任何想法或指示?

谢谢...

gbn*_*gbn 9

将“聚集索引”与“主键”分开是正确的:

  • 聚集索引是磁盘上数据的组织方式,如果
    • 狭窄的
    • 数字
    • 增加(严格单调)
  • 主键标识一行

注意:GUID 会产生较差的聚类键

在这种情况下,通过代理列,该表有 2 个候选键:

  • 产品历史ID
  • 产品编号 + 创建日期时间

假定的约定表明 ProductHistoryID 成为 PK,但您可以将 PK 保留在 (ProductNo, CreatedDateTime) 上:它将只是非集群的。这导致索引:

  • 聚集索引应该在 ProductHistoryID 上
  • (ProductNo, CreatedDateTime) 上的唯一非聚集索引

例子

CREATE TABLE Product (
    ProductHistoryID int NOT NULL IDENTITY (1,1) NOT NULL,
    ProductNo ...
    CreatedDateTime ...
Run Code Online (Sandbox Code Playgroud)

那么你可以选择

    CONSTRAINT PK_Product PRIMARY KEY CLUSTERED (ProductHistoryID)
    CONSTRAINT UQ_Product UNIQUE NONCLUSTERED (ProductHistoryID)
Run Code Online (Sandbox Code Playgroud)

或者

    CONSTRAINT PK_Product PRIMARY KEY NONCLUSTERED (ProductNo, CreatedDateTime)
    CONSTRAINT PK_Product UNIQUE CLUSTERED (ProductHistoryID)
Run Code Online (Sandbox Code Playgroud)

此外,您拥有的模式是“类型 2缓慢变化的维度


mar*_*c_s 5

我只想强调一件事:请非常小心地选择您的聚集索引!

它是SQL Server 数据库中复制最多的数据结构(假设它是您正在谈论的 SQL Server)。聚簇键也将成为表上每个非聚簇索引的一部分 - 当然在叶级,也可能在索引导航结构中。

选择聚类键时应该格外小心 - 它应该是:

  • (4 字节理想)

  • 唯一(毕竟它是“行指针”——如果你不让它独一无二,SQL Server 会——为你——在后台——为每个条目花费几个字节——乘以行数和您拥有的非聚集索引 - 可能非常昂贵!)

  • 静态(永远不要改变 - 如果可能的话)

  • 理想情况下不断增加,因此您不会以可怕的索引碎片告终(GUID 与良好的集群键完全相反 - 出于这个特殊原因)

  • 它应该是不可为空的,理想情况下也可以用 - avarchar(250)进行修复,这是一个非常糟糕的聚类键

在这些要点之后,其他任何事情都应该真正成为第二和第三级重要性......

请参阅金伯利·特里普(Kimberly Tripp)(索引女王)关于该主题的一些博客文章 - 她在博客中写的任何内容绝对是无价的 - 阅读它,消化它 - 以它为生!