我应该使用整数主 ID 吗?
Posted
技术标签:
【中文标题】我应该使用整数主 ID 吗?【英文标题】:Should I use integer primary IDs? 【发布时间】:2010-04-17 21:22:03 【问题描述】:例如,我总是为 users 表生成一个自动增量字段,但我也在他们的用户名上指定一个唯一索引。在某些情况下,我首先需要获取给定用户名的 userId,然后执行所需的查询,或者在所需的查询中使用 JOIN。这是 2 次访问数据库或 JOIN 与 varchar 索引。
与 small VARCHAR 索引相比,INT 是否有真正的性能优势?
【问题讨论】:
【参考方案1】:拥有代理主键有几个优点,包括:
当你在另一个表中有一个外键时,如果它是一个整数,它只占用几个字节的额外空间,并且可以快速连接。如果您使用用户名作为主键,则必须将其存储在两个表中 - 占用更多空间,并且在需要加入时进行比较需要更长的时间。
如果用户希望更改他们的用户名,如果您将其用作主键,您将遇到很大的问题。虽然可以更新主键,但这样做是非常不明智的,并且可能会导致各种问题,因为此键可能已发送到各种其他系统,用于链接,保存在备份中,日志已存档等。您无法轻松更新所有这些地方。
【讨论】:
感谢您的快速回复,在我的系统中,“这是 2 次访问数据库或 JOIN 与 varchar 索引”这种情况经常发生³。我应该坚持使用INT ID吗?如果是,2 次旅行或 JOIN?再次感谢! 使用连接。这将比两次访问数据库要快。连接速度很快——这就是数据库的设计目的。【参考方案2】:这不仅仅是关于性能。您永远不应该键入有意义的值,原因在其他地方都有详细记录。
顺便说一句,我经常将 int 的类型缩放到表格的大小。当我知道一个表不会超过 255 行时,我使用 tinyint 键,smallint 也是如此。
【讨论】:
【参考方案3】:除了别人说的,还要考虑表的聚类问题。
例如在 SQL Server 中(可能还有其他供应商),如果主键也用作表的聚集索引(这很常见),则递增整数比其他字段类型更有优势。这是因为输入新行时使用的主键总是大于前一行,这意味着新行可以存储在表的末尾而不是中间(同样的场景可以 使用其他字段类型创建主键,但整数类型更适合自己。
将此与 guid 主键进行比较 - 必须将新行插入到表的中间,因为 guid 是非顺序的,因此插入效率非常低。
【讨论】:
【参考方案4】:首先,很明显,在小型表上,它对性能没有影响。只有在非常大的表上(多大取决于许多因素),它才会因为以下几个原因而有所不同:
使用 32 位只会消耗 4 个字节的空间。据推测,您的用户名将超过四个非 Unicode 字符,因此占用超过 4 个字节的空间。使用的空间越多,页面上的数据量就越少,索引越胖,您产生的 IO 就越多。
您的字符列将需要使用 varchar 而不是 char,除非您强制每个人都拥有相同大小的用户名。这也会对性能和存储产生很小的影响。
除非您使用二进制排序排序规则,否则系统在比较两个字符串时必须进行相对复杂的匹配。两列是否使用相同的排序规则?对于每个字符,它们的大小写是否相同?匹配方面的大小写和重音规则是什么?等等。虽然这可以快速完成,但在非常大的表中,与匹配整数相比,这需要更多的工作。
我不确定您为什么必须两次访问数据库或加入 varchar 列。为什么您不能在数据库中进行一次访问(创建返回您的新 PK),在该数据库中您加入整数 PK 上的 users 表?
【讨论】:
以上是关于我应该使用整数主 ID 吗?的主要内容,如果未能解决你的问题,请参考以下文章
我应该使用复合主键来加速 PostgreSQL 中基于时间戳的选择吗?
使用带有本地数据库文件 (Sdf) 的实体框架生成 C# 整数主键