我已经厌倦了向我们研发团队中的每一位新初级开发人员解释为什么他应该使用主键以及如何做到这一点。所以我决定写一份小白皮书,每个新开发人员都应该阅读。这是它的草稿。
免责声明:
- 我知道并理解聚集索引和主键之间的区别
- 在下面的问题中PRIMARY KEY表示PRIMARY KEY CLUSTERED,WITHOUT PRIMARY KEY表示WITHOUT PK AND CLUSTERED INDEX
- 请注意,这是面向初级而非 SQL 程序员的白皮书
- 他们所做的所有事情 - 在进入主要开发分支之前进行审查
- 我不打算向他们解释——什么时候使用聚集索引和非聚集主键会有好处——否则我会陷入过早的优化地狱
问题是——我还应该在文档中添加什么?可能是——我应该改变什么?以及更详细地解释什么?
草稿来了:
- 主键必须约束数据库中的任何表。
- 如果没有 PK,表将被视为堆,SQL Server 对此类数据的使用非常有限——我唯一应该说它是合适的——一个用于从 SQL Server 引擎外部快速批量加载数据的缓冲区。
- 避免使用自然主键。主要是因为它们的自然(高斯)分布。例如,在具有基于 Family 和 Name 的主键的 PhoneBook 表中,将有许多 Smiths 和 Wilsons,而 Zimmerbergs 少得多,这说明,包含 Smiths 和 Wilsons 的页面将比其他页面更频繁地被拆分,并且查询也更频繁 - 这乘以性能影响。这会导致性能下降,因为主键的页面已满,并且大多数搜索将命中 PK 的稀疏页面。
此外,即使使用(我希望)平坦分布的 SSN 或 ID 号码,因为 PK 也不能解决 PK 页面拆分的问题,因为这些号码没有任何组织顺序。
- 次要 - 自然 PK 通常是复合的。这会创建复合外键和宽索引,从而损害性能。所以, ...
- 避免使用复合 PK。最好使用简单的代理 PK 和复合 UNIQUE 索引,而不是一体式复合 PK,因为它会导致复合 FK 和宽索引,因为语句导致表上的每个二级索引都必须包含整个 PK。
- 避免使用整数或唯一标识符类型以外的代理主键
- 在数据库设计阶段,识别实体和对应的表非常重要,这些实体和对应的表可能具有“数以亿计”的行,或者表的键不仅必须是全表唯一的,而且必须是数据库甚至世界唯一的,或者必须通过这个键在几个跳表上与其他表连接 - 这个表最好有 UUID PK,其他 - 普通整数,因为 SQL Server 非常好地调整为使用整数 PK。
- 这两种类型可以保证向量分布(IDENTITY 或 NEWSEQUENTIALID())和单调序列。
- 主要数据库设计规则 -花 20 分钟进行深思熟虑的设计将在生产数据库维护期间节省数天甚至数周的时间
您在这里混淆了各种概念,主要错误是主键!=聚集键。由于这种误解,大多数指导都是不正确的。老实说,您可能不适合编写这些指南。
您的观点与数据库设计无关:自然键或代理键的选择是概念和逻辑模型完成后的实施决策
除了评论和其他答案:
编辑:“复合键”的例子
假设:t1 有孩子 t2 有孩子 t3
如果你在 t3 中有 t1 的密钥(复合密钥),你可以直接连接 t1 和 t3。
t1 键也是 t3 键的左侧列,因此您不需要额外的索引
使用代理键/FK,你必须通过 t2 加入
你需要在 t2 和 t3 中的 FK 列上有额外的索引
后一种选择带有“始终使用代理键”教条
为什么不从规范化的基础知识和执行关系完整性的能力开始呢?
此外,如果您处于使用事务复制的环境中并且该表有可能被复制,您将需要一个主键。
以下是您可以与这些初级程序员分享的一些建议阅读材料: