我知道这是主观的,但我想知道人们的意见,并希望在设计sql server表结构时可以应用一些最佳实践。
我个人觉得在固定(最大)长度varchar上键入一个表是禁忌,因为它意味着必须在使用它作为外键的任何其他表中传播相同的固定长度。使用int
,将避免必须在整个板上应用相同的长度,这必然导致人为错误,即1个表具有varchar (10)
,而另一个varchar (20)
。
这听起来像是最初设置的噩梦,而且意味着将来维护表格也很麻烦。例如,假设keyed varchar列突然变成12个字符而不是10个字符。你现在必须去更新所有其他表格,这可能是一个巨大的任务年代。
我错了吗?我错过了什么吗?我想知道其他人对此的看法,以及坚持使用int作为主键是避免维护噩梦的最佳方法。
答案 0 :(得分:39)
答案 1 :(得分:17)
我肯定会建议在每个表中使用INT NOT NULL IDENTITY(1,1)
字段作为
主键。
使用IDENTITY字段,您可以让数据库处理确保它真正唯一的所有细节,并且INT数据类型只有4个字节并且已修复,因此它更容易且更适合用于主数据库表格中的(和群集)键。
你是对的 - INT是一个INT是一个INT - 它不会改变它的大小,所以你不必再重新创建和/或更新你的外键关系。
使用VARCHAR(10)或(20)只占用太多空间 - 10或20个字节而不是4个,而且许多人都不知道 - 聚类键值将在每个索引上重复在表上的每个非聚集索引上输入,因此可能会浪费大量空间(不仅仅是在磁盘上 - 这很便宜 - 而且还在SQL Server的主内存中)。此外,由于它的变量(可能是4,可能是20个字符),因此SQL服务器更难以正确维护良好的索引结构。
马克
答案 2 :(得分:4)
我同意一般来说INT(或身份)字段类型是大多数“普通”数据库设计的最佳选择:
也就是说,您还需要了解您的数据。如果你打算通过一个带符号的32位int,你需要考虑unsigned。如果你想要通过它,也许你想要的64位整数。或者您可能需要UUID / hash来更轻松地在数据库实例/分片之间进行同步。
不幸的是,它取决于和YMMV,但我肯定使用int / identity,除非你有充分的理由不。
答案 3 :(得分:3)
就像你说的那样,一致性是关键。我个人使用未签名的整数。除非你正在使用大量数据,否则你不会用完它们,并且你总是可以知道任何关键列需要是那种类型,你永远不必为各个列寻找合适的值。
答案 4 :(得分:2)
基于无数次执行此练习然后用结果支持系统,有一些警告说明INT总是更好。一般来说,除非有理由,否则我会同意。然而,在战壕中,这里有一些优点和缺点。
<强> INT 强>
<强> GUID 强>
难以使用 - 即使是经验丰富的程序员也无法记住guid。在进行故障排除时,必须复制和粘贴查询标识符通常很令人沮丧,尤其是在使用远程访问工具完成支持时。经常引用SELECT * FROM Xxx WHERE ID = 7比SELECT * FROM Xxx WHERE ID ='DF63F4BD-7DC1-4DEB-959B-4D19012A6306'
索引 - 对guid字段使用聚簇索引需要对数据页进行不断的重新排列,并且索引效率不如INT甚至短字符串。它可以扼杀性能 - 不要这样做。
<强> CHAR 强>
答案 5 :(得分:1)
对于best performance,99.999%的时间主键应该是一个整数字段。
除非您要求主键在数据库中的多个表或多个数据库中是唯一的。我假设您询问MS SQL-Server,因为这是您的问题被标记的方式。在这种情况下,请考虑使用GUID字段。虽然优于varchar,但GUID字段性能不如整数。
答案 6 :(得分:1)
使用INT。你的积分都是有效的;我会优先考虑:
1&amp; 2需要开发人员的时间/精力/精力。 3&amp; 4你可以扔硬件。
答案 7 :(得分:1)
如果Joe Celko在这里,他会有一些刺耳的话......; - )
我想指出,INT作为一项严格而快速的规则并不总是合适的。假设您有一个车辆桌子,上面有各种类型的汽车卡车等。现在说你有一个VehicleType表。如果您想获得所有卡车(可以使用INT身份种子):
SELECT V.Make, V.Model
FROM Vehicle as V
INNER JOIN VehicleType as VT
ON V.VehicleTypeID = VT.VehicleTypeID
WHERE VT.VehicleTypeName = 'Truck'
现在,在VehicleType上使用Varchar PK:
SELECT Make, Model
FROM Vehicle
WHERE VehicleTypeName = 'Truck'
代码更清洁,你避免加入。也许连接不是世界末日,但如果你的工具箱中只有一个工具,那么你就会错过一些提高性能和更清晰模式的机会。
只是一个想法。 : - )
答案 8 :(得分:0)
虽然通常建议使用INT
,但这实际上取决于您的情况。
如果您关注可维护性,那么其他类型也是可行的。例如,您可以非常有效地使用Guid作为主键。有理由不这样做,但一致性不是其中之一。
但是,是的,除非你有充分的理由不这样做,否则int最容易使用,并且最不可能导致任何问题。
答案 9 :(得分:0)
使用PostgreSQL,我通常使用“Serial”或“BigSerial”数据类型来生成主键。这些值是自动递增的,我总能找到易于使用的整数。它们基本上等同于设置为“auto_increment”的MySQL整数字段。
答案 10 :(得分:0)
人们应该认真考虑32位范围是否足以满足您的需求。 Twitter的状态ID是32位INT,当他们用完时他们遇到了麻烦。
在这种情况下是否使用BIGINT或UUID / GUID是有争议的,我不是硬核数据库人,但是UUID可以存储在固定长度的VARCHAR中,而不必担心你需要更改字段大小
答案 11 :(得分:0)
我们必须记住,表的主键不应该具有“业务逻辑”,它应该只是它所属记录的标识。遵循这个简单的规则,int和特别是identity int是一个非常好的解决方案。通过询问varchar我猜你的意思是使用例如“全名”作为“人”表的关键。但是,如果我们想将名称从“George Something”改为“George A. Something”呢?该领域的规模是多少?如果我们改变大小,我们也必须改变所有外表上的大小。所以我们应该避免键上的逻辑。有时我们可以使用社交ID(整数值)作为键,但我也避免使用它。现在,如果一个项目有扩展的前景,你应该考虑使用Guids(uniqueidentifier SQL类型)。
答案 12 :(得分:0)
请记住,这是一个非常古老的问题,我仍然希望将未来读者使用varchar与代理键进行讨论: