可能重复:为什么将int用作查找表的主键?




到目前为止,我已经习惯于为每个表创建一个ID列,并且它的实用性使我无需考虑决策

我大学的教授建议班级从一个或多个字段中制作主键,这些字段构成每列的唯一信息。是的,我想养成应用自然键而不是替代键的习惯。在Wikipedia上,列出了替代键的优缺点,我严格建议使用本文

我已经看到人们对所有内容都使用整数ID字段,并且没有人判断此方法,因为


它“看起来”高效”
使用了一个数字字段,并且由于其每行的大小而看起来更酷


我开始考虑一个额外的ID字段只是创建冗余数据,没有实际好处。那么,当我可以将其他列用作键字段时,为什么还要创建一个ID列呢?


如果您的ID字段为32位,则已经等于4个ASCII字符

如果您的Id字段是64位整数,则为8个字符的字符串,因此它实际上并没有节省那么多的内存(这里暗示的是用于比较的内存。额外的id列已添加到使用的内存(包括HDD和RAM))
额外的ID字段会使索引成本加倍,因为您还将
索引可以用作主键的唯一字段。

如果需要用作键字段的数据,则可以进行额外的联接,例如,如果您在一个
博客帖子中存储了唯一的用户ID,以显示作者的姓名,则可以进行联接查询,如果
您的关键字段是作者的姓名,则不需要加入,因为
您将相关数据存储在博客帖子表中。具有有意义数据的外键
字段减少了子查询或联接的需求





创建一个额外的id字段“增加”内存负载,这不是唯一字符串字段的替换,如果不使用整数替换
char-varchar字段,则添加一个额外的
列,它会创建额外的数据流。因此,
数据存储区的任何比较都应在“字符串”和“ int +字符串”之间进行。添加
整数id字段不会节省空间。另一方面,


分配从用户输入获取值的主键数据,可能会出现问题,因为人们可以输入例如其社会保险号码错误,并且由于独特的政策,想要注册的实际人将
无法注册。可以
通过在原始号码上添加一个或多个额外的数字来避免这种情况。

其他资源:



自然vc代理键的比较

我从阅读文章中得出的结论是,无论何时我都应该使用自然键不必像考虑标准那样,每次都不必考虑自然键并使用代理键。

#1 楼

1-更快。整数字段上的JOIN比字符串字段或字段组合上的JOIN快得多。比较整数比字符串更有效。

2-更简单。与基于不同数据类型的其他字段的组合相比,基于单个数字字段映射关系要容易得多。

3-它与数据无关。如果您在ID上进行匹配,则无需担心关系的改变。如果您的名字匹配,如果他们的名字改变(即婚姻),您该怎么办?

4-如果在地址上匹配,如果有人移动该怎么办?4-效率更高如果在(自动递增)int字段上聚类,则可以减少碎片并减小数据集的整体大小。这也简化了涵盖您的关系所需的索引。

编辑

对于刚添加的特定点:

1和2-仍然很多比起字符串,比较int更快。您还可以方便地忽略存储可变长度字段的长度(通常每行每个字段2个字节)所需的开销。

3-如果在ID字段上聚类,那么它不会添加任何额外内容。因为您使用的行ID更有效,所以可以节省空间。

4-然后,当该人更改其用户名时,您的链接就会全部断开。

5-您真的不这样做不知道你在说什么。您确实必须存储数据,这是正确的,但在int上进行索引和JOIN的效率要比在其他字段的组合上高效。

评论


“它与数据无关”作为前端开发人员,这对我来说是最重要的。如果数据曾经在前端应用程序中使用,尤其是正在积极开发中的数据,则可以节省大量开发时间。 id始终是URL安全的,不区分大小写的,并且不需要其他逻辑。可以使用良好的API在服务层解决此问题,但实际上,它通常会变成前端开发人员编写大量不应在前端存在的代码。在项目的上下文中,任何比id字段复杂的事情都会带来令人惊讶的工作量。

– Ramblinjan
15年7月16日在20:37

“这与数据无关”-如果一切都发生变化,您怎么知道它仍然是同一个人?

– Alexey
18年5月7日在10:06

@Alexey,您知道是同一个人,因为有一个更新事务会更改标识信息。所有相关记录都通过未更改的ID链接,但是属性可以全部更改,并且一切仍然有效。

– JNK
18年5月18日在13:08

#2 楼

因为人们从经验中学到,使用这些字段会导致问题。

我已经开发数据库应用程序20年了。最关键的是,我花了五年时间处理数据仓库。在早期,选择其他领域似乎还可以。然后,我们发现重复的记录,有时缺少唯一的验证,有时(经常)用户提供了现在需要合并的其他信息,等等,并且合并和管理记录是一场噩梦。

甚至更特别!),当标识符“似乎”是唯一的时,这可能不是事实。例如:美国社会安全号码。它应该是一个人唯一的,对吗?当然可以,但是如果过去用用户错误输入的某些记录与SSN一起输入,该怎么办?现在,使用新的有效数字输入新记录可能会出现冲突问题。附带说明一下,也不应该显示主键,因为它们会导致用户对它们的假设,并且也不利于网站URL的最佳安全性模型。
始终考虑-用户是否会将该URL标记为书签并

所以人们了解到:

当代理具有以下功能时,不要使用“代理键”(例如SSN)作为主键“任何”业务价值或意义。
请使用唯一且不是从应用程序数据派生的主键。

评论


“因为人们从经验中学到,不这样做会导致问题。”-反之亦然。

–有一天
11年11月24日在13:24

#3 楼

如果要查找数据,则确实要基于一个或多个整数字段。这就是为什么许多人为此使用ID字段的原因。
但是,如果您有用于多对多关系的表,则实际上并不需要它。
说您有以下两个表:

表新闻
id整数
标题varchar
项目文本

表标签
id整数
名称varchar

要为新闻中的每个项目添加一个或多个标签,因此要创建表格:

表格news_tags
news_id整数
tags_id整数

在这种情况下,实际上不需要创建额外的id列,因为您根本不需要它。

#4 楼

大多数人默认使用自动递增INT作为主键,因为这是识别行的最简单方法,特别是当您需要在表之间定义关系时。

如果足够幸运的话要对已经具有唯一标识符的对象进行建模,那么我会考虑将其用作主键(例如,汽车的VIN或手机的IMEI)。

也有所谓的复合键,基本上数据库中的两个或多个字段唯一标识该行。与我合作过的大多数开发人员(包括我自己)通常都不使用此功能。同样,不这样做的主要原因是,这使得管理表之间的关系更加困难。

在自然界中,事物不是由唯一的标识符定义的,而是由它们与其他实体的关系定义的。 id字段实际上只是关系数据库的产物。这是整个对象关系映射(ORM)问题的基础。

我意识到这是一门课程,您必须了解其内容,但是请不要忘记,还有其他建模方法关系数据库之外的数据。 NoSQL运动证明了这一点。

评论


这里的信息很好,但是您的两个示例都是应该是唯一标识符的情况,但在一般情况下不是。 VIN和IMEI编号都是出于犯罪目的而克隆的,并确保启动希望它们唯一的系统。

– Mark Storey-Smith
2011年11月23日23:07

如果已知犯罪分子会克隆某些标识符,那么这肯定是强制执行属性必须唯一的业务规则的一个很好的理由-即不要“绊倒”系统,而是要防止所述重复值进入数据库,并且从而将任何此类尝试标记为潜在的欺诈或错误,需要进一步调查。

– nvogel
2015年1月5日,12:49

#5 楼

如果您可以将其他字段用作主键,那很好。但是,由于您已在[sql-server]下对此进行了标记,因此我将能够添加一些信息...


如果您需要复制从未有过或不需要的表主键,那么您就必须创建一个。如果您有此id列,那么就很容易。<=就像id
那样,ID列,尤其是那些IDENTITY列也很适合作为索引(有时),因为它们几乎永远不会更新,如果不这样做,删除表格中的行,可以减少索引碎片。
ID列不必总是仅仅是标识列。您可以存储一个date_id(对于某些有意义的表),如果它是唯一的(例如我说的..例如,您有一个表,其中一行等于一天),则可以将其用作键或索引
当您没有create_date / entry_date列并且需要按输入顺序检查数据时。使用ID列作为标识可以实现这一目的。
ID可以充当以及一个外键。


#6 楼

虽然复合键起作用,但有时可以更轻松地使用单个主键。例如,在执行删除操作时,很容易单挑特定的行。

搜索数字键通常也更有效。

#7 楼

因为ID用于识别所有内容。以用户为例-按用户名搜索用户比按Integer(ID)搜索用户要慢

评论


在现实生活中,没有人用自己的ID互相搜索。

–UğurGümüşhan
2011年11月22日在20:21

@UurGümühan:我的意思是在后端-搜索1比搜索Admin快

–马丁
11年11月22日在21:07