主键的 SQL 表设计(最佳实践)

5 database-design sql-server primary-key

我有一个User由以下列组成的表格:

  • ID(自动生成的 GUID)
  • 用户名
  • 密码
  • 电子邮件
  • 地址 ID (GUID)

这链接到Address包含以下列的表(以一对一 [1-1] 关系)

  • ID(自动生成的 GUID)
  • 街道
  • 其他地址字段

这似乎是这样做的合乎逻辑的方式(对我来说)。但有人告诉我,它可能包含冗余列(AddressID),我应该用EntityID代替Address.ID

将少一列,但该Address表将有自己的ID列。

您推荐哪种做法?有没有更快的执行?在父母/子女关系的背景下什么是最好的?对表演有影响吗?

mar*_*c_s 6

我同意 Maess - 如果您有不同的实体,那么每个实体都应该有自己的 ID 列。但是我强烈反对将 GUID 用于主键 - 或者更具体地说 - 用于 SQL Server 的集群键。

GUID 似乎是您的主键的自然选择 - 如果您真的必须这样做,您可能会争辩说将它用于表的 PRIMARY KEY。我强烈建议不要使用 GUID 列作为集群键,SQL Server 默认情况下会这样做,除非您明确告诉它不要这样做

你真的需要把两个问题分开:

1)主键是一个逻辑结构 - 唯一且可靠地标识表中每一行的候选键之一。这可以是任何东西,实际上 - 一个 INT、一个 GUID、一个字符串 - 选择最适合您的场景的内容。

2)聚簇键(定义表上“聚簇索引”的一列或多列)——这是一个物理存储相关的东西,在这里,一个小的、稳定的、不断增加的数据类型是你最好的选择——INT或 BIGINT 作为您的默认选项。

默认情况下,SQL Server 表上的主键也用作集群键 - 但不必如此!当将以前的基于 GUID 的主键/集群键分解为两个单独的键时,我个人看到了巨大的性能提升 - GUID 上的主(逻辑)键和单独的 INT IDENTITY 上的集群(排序)键(1, 1) 列。

正如金伯利·特里普Kimberly Tripp) ——索引女王——和其他人多次说过——作为集群键的 GUID 不是最佳的,因为由于它的随机性,它会导致大量的页面和索引碎片,并且通常会导致性能不佳。

是的,我知道 -newsequentialid()在 SQL Server 2005 及更高版本中存在 - 但即使这样也不是真正和完全连续的,因此也遇到与 GUID 相同的问题 - 只是不那么突出。

然后还有另一个问题需要考虑:表上的聚簇键也将添加到表上每个非聚簇索引的每个条目中 - 因此您确实希望确保它尽可能小。通常,对于绝大多数表来说,具有 2+ 十亿行的 INT 应该足够了 - 与作为集群键的 GUID 相比,您可以在磁盘和服务器内存上节省数百兆字节的存储空间。

快速计算 - 使用 INT 与 GUID 作为主键和集群键:

  • 具有 1'000'000 行的基表(3.8 MB 与 15.26 MB)
  • 6 个非聚集索引(22.89 MB 与 91.55 MB)

总计:25 MB 与 106 MB - 这只是在一张桌子上!

还有一些值得深思的东西——金伯利·特里普 (Kimberly Tripp) 的优秀作品——阅读它,再读一遍,消化它!这是 SQL Server 索引的福音,真的。


小智 1

如果表代表实体而不是关系,则最佳实践是它有自己的主键。因此,User 和 Address 都应该有自己的 PK,AddressID 应该是 User 表中的 FK。您遵循的方法是正确的。