SQL Server:需要我的白皮书的主键建议

Ole*_*Dok 0 database-design sql-server database-tuning database-theory

我已经厌倦了向我们研发团队中的每个初级开发人员解释为什么他应该使用主键以及如何使用。所以我决定写一个小白皮书,每个新开发人员都应该阅读。这是它的草稿。

免责声明:

  1. 我知道并理解聚集索引和主键之间的区别
  2. 在以下问题中,PRIMARY KEY 表示 PRIMARY KEY CLUSTERED,而 WITHOUT PRIMARY KEY 表示没有 PK 和 Clustered INDEX
  3. 请注意,这是面向初级而非 SQL 程序员的白皮书
  4. 他们所做的所有事情 - 在进入主要开发分支之前进行审查
  5. 我不会向他们解释——什么时候使用聚集索引和非聚集主键会有好处——否则我会陷入过早的优化地狱

问题是- 我还应该在文档中添加什么?可能是——我应该改些什么呢?更详细的解释是什么?

草稿来了:

  • 主键必须约束数据库中的任何表。
  • 如果没有 PK,一个表被认为是一个堆,而 SQL Server 对这种类型的数据的使用非常有限——我唯一应该说它是合适的——一个用于从 SQL Server 引擎外部快速批量加载数据的缓冲区。
  • 避免使用自然主键。主要是因为它们的自然(高斯)分布。例如,在具有基于 Family 和 Name 的主键的 PhoneBook 表中,Smiths 和 Wilsons 将很多,而 Zimmerbergs 少得多,这表明,包含 Smiths 和 Wilsons 的页面将比其他页面更频繁地拆分,并且也更频繁地查询 - 这成倍增加性能影响。这会导致性能下降,因为主键的页面很满,并且大多数搜索都会命中 PK 的稀疏页面。

此外,即使使用具有(我希望)扁平分布的 SSN 或 ID Number,因为 PK 也不能解决 PK 的页面拆分问题,因为这些数字没有任何组织顺序。

  • 次要 - 自然 PK 通常是复合的。这会创建复合外键和宽索引,从而损害性能。所以, ...
  • 避免使用复合 PK。使用简单代理 PK 和复合 UNIQUE 索引比使用多合一复合 PK 更好,因为它会导致复合 FK 和宽索引,这是由于声明,带有 PK 的表上的每个二级索引都必须包含整个 PK。
  • 避免使用除整数或唯一标识符类型以外的代理主键
  • 在数据库设计阶段,识别实体和相应的表非常重要,这些表可能有“无数”的行,或者表的键不仅必须是表范围唯一的,而且是数据库甚至世界唯一的,或者必须是通过这个键在几个跳表上与其他表连接 - 这个表最好有 UUID PK,其他表 - 普通整数,因为 SQL Server 很好地调整为使用整数 PK。
  • 这两种类型可以保证向量分布(IDENTITY 或 NEWSEQUENTIALID())和单调序列。
  • 主要的数据库设计规则 -花费 20 分钟进行深思熟虑的设计将在生产数据库的维护期间节省数天甚至数周的时间

Mar*_*ith 7

您在这里混淆了各种概念,主要错误是主键!= 聚集键。由于这种误解,大多数指南是不正确的。老实说,您可能不适合编写这些指南。

  • 主键 != 聚集键
  • 唯一标识符导致非常差的聚集键
  • SQL Server 不是“很好地调整以使用整数 PK”。上面的链接介绍了窄聚集键的情况,这与 SQL Server 是否针对整数聚集键进行优化无关。


gbn*_*gbn 7

您的观点与数据库设计无关:选择自然键或代理键是概念和逻辑模型完成后的实现决策

除了评论和其他答案:

  • 一些自然键效果很好,例如货币或语言代码(CHF、GBP、DE、EN 等)
  • 避免复合键迫使你总是加入中间表(而不是简单的)父-孙
  • 为链接表添加不必要的代理键

编辑:“复合键”示例

假设:t1 有孩子 t2 有孩子 t3

  • 如果您在 t3(复合键)中有 t1 的键,您可以直接连接 t1 和 t3。
    t1 键也是 t3 键的左侧列,因此您不需要额外的索引

  • 使用代理键/FK,您必须通过 t2 加入
    您需要在 t2 和 t3 中的 FK 列上有额外的索引

带有“始终使用代理键”教条的后一种选项

  • 增加复杂性
  • 减少或逆转磁盘空间“节省”