我知道在设计表时使用主键更好。
但我想知道何时设计主键,需要设置auto_increment?
如果完成,有什么好处?
我听,这可以保持b-tree的稳定,但我不知道为什么?
如果table有一个唯一列,那么将唯一列设置为主键或添加新列'id'作为auto_increment主键更好?
你能帮帮我吗?感谢。答案 0 :(得分:6)
我知道在设计表时使用主键会更好。
实际上,无密钥表是multiset(因为它允许重复),因此不是严格意义上的关系(这是一个集合),因此您的数据库实际上不会是"关系"
请注意"主要" (PRIMARY KEY)和" alternate" (UNIQUE约束)键是logically equivalent。
但我想知道何时设计主键,需要设置auto_increment?
您实际上是在问多个问题:
(1)的答案是"几乎总是"。当数据不重要时,有一些非常罕见的情况。出于性能原因你可能会跳过它,但这种情况非常罕见。
(2)的答案是"它取决于" - 可以找到主要的利弊here。
(3)的答案取决于您是否需要从数据库中独立生成键(例如,在断开连接时,或在连接到其他数据库时)。如果是,您可以使用GUID(显然不能自动递增,但可以独立生成)。如果不是,那么你可以使用整数 - 它们更紧凑,通常更快。
最后,如果你达到(4),那么你几乎肯定想让它自动递增,原因如下所述。
如果完成,有什么好处?
SELECT MAX(ID) + 1 FROM ...
,则无法保证其他客户端不会同时尝试执行相同的操作,并最终会产生相同的结果(随后导致密钥违规)。如果表格具有唯一列,那么将唯一列设置为主键或添加新列“id' as auto_increment主键?
如果属性在"逻辑级别"本质上是唯一的,那么相应的表列必须是唯一的(通过PRIMARY KEY或UNIQUE约束),无论您以后决定添加代理密钥。
答案 1 :(得分:5)
我想知道何时设计主键,需要设置auto_increment?
不,这不是绝对必要的。有时自然键很好。
如果完成,有什么好处?
使用自动增量代理键的优点:
使用自然键的优点:
shoes
引用colors
的表格需要进行联接。但是,如果您使用颜色名称作为 colors
的主键,则该值已经成为shoes
表的一部分。不需要代理自动增量键的其他情况:
我听,这可以保持b-tree的稳定,但我不知道为什么?
将值插入B树中间的任意位置可能会导致索引重组成本高昂。
这里有一个动画示例:http://www.bluerwhite.org/btree/
查看示例“将密钥33插入B树(带拆分)”,其中显示了将值插入到溢出它的B树节点中的步骤,以及B树响应的内容
现在想象一下,示例说明只显示了更深层的B树的底部(就像索引B树有数百万个条目的情况一样),填充父节点本身就可以了溢出,并强制拆分操作继续向上树中的更高级别。如果已经填充了树顶部的所有祖先节点,这可以一直持续到树的最顶层。
由于节点分裂并且必须重新构建,它们可能需要更多空间,但它们存储在数据库文件的某些页面上,其中没有空余空间。因此,存储引擎必须将索引的某些部分重定位到文件的另一部分,并且可能只针对单个INSERT重写大量索引页。
自动增量值自然总是插在B树的最右边。正如@ BrankoDimitrijevic在下面的评论中指出的那样,这并不会降低它们导致如此费力的节点分裂和重组到索引的可能性。但是B树实现代码可以通过其他方式针对这种情况进行优化,有些则可以。
如果table有一个唯一列,那么将唯一列设置为主键或将新列'id'添加为auto_increment主键更好?
如果唯一列也是非可空的,则可以将其用作主键。主键要求所有列都不可为空。
答案 2 :(得分:0)
拥有一个自动增量PK可以轻松创建一个永远不需要更改的密钥,从而可以轻松地在其他表中引用。
如果您的数据具有唯一且无法更改的自然列,则您也可以使用它们。提醒你大多数事情永远不会改变"如果有足够的时间,就像某人的社会保障号码那样,往往会这样做......
为简单起见,我总是使用PK的自动增量(标识)列。
答案 3 :(得分:-1)
感谢@Branko Dimitrijevic通过描述SURROGATE KEYS
的角色并进入讨论的中心来打开关系数据库主键(PK' s)的主题。根据定义,代理键除了它们在表中每个记录中的值之间的唯一性之外,没有任何内在含义。
还要感谢@Mattias Åslund您的额外智慧:
请注意大多数事情"永远不会改变"如果有足够的时间,就像某人的社会保障号码那样,往往会这样做......
我补充说,即使选择的值为"不可更改"实际上并没有改变,支持的业务或组织本身的规则也可能随着时间的推移而变化,从而可能影响给定设计的核心假设。
有关跟踪个人的人口统计和生物识别关键值整合的有用讨论,请参阅计算机专业人员社会责任提出的Choosing an Appropriate Key for New Databases部分。
我打算通过围绕特定示例设计的讨论来处理这篇文章的评论,以解释分配不是代理的主键时可能出错的事情类型键。其中许多假设来自实际应用的观察。由于其他系统和数据源依赖于其假设而将其设计引入其他业务流程的复杂性,因此很好地记住了它们。
设计和样本数据如下,从臭名昭着的臭名昭着的Scott / TIGER数据库设计中借用。
MySQL 5.5.32架构设置:
CREATE TABLE employee
(
fake_ssn varchar(15) primary key,
last_name varchar(40),
first_name varchar(40),
dept_id varchar(15),
hire_date date,
salary int,
email varchar(100)
);
INSERT INTO employee
(fake_ssn, last_name, first_name, dept_id, hire_date, salary,
email)
VALUES
('130-60-0101', 'MARLOWE', 'JACOB', '1200-05', date('2009/01/25'),
8000, 'jacob@some-company.com'),
('967-22-5025', 'CRACHITT', 'BOB', '1200-05', date('2010/02/05'),
500, 'bobc@some-company.com'),
('040-36-5555', 'PERRY', 'VICTORIA', '1200-02', date('2011/05/25'),
2700, 'vperry@some-company.com'),
('203-89-1010', 'STEVENS', 'KEVIN', '2955-03', date('2007/04/25'),
1800, 'kevin.stevens@some-company.com'),
('409-99-1111', 'MCLANE', 'JONATHAN', '2955-03', date('2009/03/02'),
4200, 'jon.j.mclane@some-company.com');
CREATE TABLE department
(
dept_id varchar(15) primary key,
dept_manager varchar(40),
dept_title varchar(40)
);
INSERT INTO department
(dept_id, dept_manager, dept_title)
VALUES
('1200-05', 'MARLOWE', 'FINANCE'),
('1200-02', null, 'HR'),
('2955-03', 'JOHNM', 'MARKETING');
COMMIT;
查询1 :
SELECT fake_ssn, last_name, first_name, dept_id, hire_date,
salary, email
FROM employee
<强> Results 强>:
| FAKE_SSN | LAST_NAME | FIRST_NAME | DEPT_ID | HIRE_DATE | SALARY | EMAIL |
|-------------|-----------|------------|---------|---------------------------------|--------|--------------------------------|
| 040-36-5555 | PERRY | VICTORIA | 1200-02 | May, 25 2011 00:00:00+0000 | 2700 | vperry@some-company.com |
| 130-60-0101 | MARLOWE | JACOB | 1200-05 | January, 25 2009 00:00:00+0000 | 8000 | jacob@some-company.com |
| 203-89-1010 | STEVENS | KEVIN | 2955-03 | April, 25 2007 00:00:00+0000 | 1800 | kevin.stevens@some-company.com |
| 409-99-1111 | MCLANE | JONATHAN | 2955-03 | March, 02 2009 00:00:00+0000 | 4200 | jon.j.mclane@some-company.com |
| 967-22-5025 | CRACHITT | BOB | 1200-05 | February, 05 2010 00:00:00+0000 | 500 | bobc@some-company.com |
查询2 :
SELECT dept_id, dept_manager, dept_title
FROM department
<强> Results 强>:
| DEPT_ID | DEPT_MANAGER | DEPT_TITLE |
|---------|--------------|------------|
| 1200-02 | (null) | HR |
| 1200-05 | MARLOWE | FINANCE |
| 2955-03 | JOHNM | MARKETING |
(FAKE
名称只是提醒您这些都是随机生成的值。)虽然这通常是一种流行的&#34; unqiue&#34;根据美国社会保障局的数据,人员记录和数据库的价值并不是唯一的。这也是有问题的,因为这个价值及其转让受到最近通过的隐私法的严格监管。
即使使用包含中间首字母创建的其他组合,不知何故仍然有太多同名的人。看看社会保障管理局对于2012年出生的婴儿的注册名称所说的话:
从现在开始的二十年,当2012年 JACOB 和 SOPHIA 从学校毕业时,他们将涌入数千人的劳动力队伍中其他人喜欢他们......
按婚姻或法律原因进行的名称更改也会依赖其作为业务键值的数据库记录的参照完整性受到威胁。
有些公司会尝试从其他值派生密钥以生成SMART KEYS
。在实践中观察这些类型的钥匙根本不聪明。示例中的值:1200-02
,1200-05
,2955-03
旨在类似于&#34;智能密钥&#34;。第一个值可能是公司园区或多地点业务的街道地址或建筑物编号。第二个值(&#34; -02&#34;,&#34; -03&#34;,&#34; -05&#34;)可能是部门所在建筑物的楼层。
更改建筑物,移动部门或完全重新定位业务会使DEPARTMENT ID
的这种位置依赖性变得无用。
这个很微妙,但这种关系连接存在漏洞。 MANAGER
也是一名员工,它使EMPLOYEE
和DEPARTMENT
之间的关系联接成为循环联盟:
MANAGER
(来自DEPARTMENT
)是EMPLOYEE
表上的外键约束,还是DEPT_ID
(FROM EMPLOYEE
)是DEPARTMENT
表上的外键约束吗?如果您放弃MANAGER
与EMPLOYEE
(LAST_NAME
或FIRST_NAME
+ LAST_NAME
)上的某个关键列之间的外键约束,则可能存在非法风险MANAGER
的统一值。
......看着
<强> Query of The DEPARTMENT
Table 强>:
| DEPT_ID | DEPT_MANAGER | DEPT_TITLE |
|---------|--------------|------------|
| 1200-02 | (null) | HR |
| 1200-05 | MARLOWE | FINANCE |
| 2955-03 | JOHNM | MARKETING |
DEPT_MANAGER
表中DEPARTMENT
的错位,因为部门经理的名称有三种不同的表示方式:none(null),ALL-CAPS姓氏,ALL-CAPS First姓名,最后一个姓名。
从这篇文章中得出的一个重要教训是,通过整合派生值,使密钥更多而不是密钥,根据业务规则的假设创建值会限制数据库设计的灵活性,因为如果业务规则发生更改,则主键或连接键值等值也会更改。
作为业务应用程序的开发人员或维护人员,如果您已控制并拥有代表业务应用程序本身内部结构的部分,则您(或您的团队)能够更好地支持当前的业务条件。主键实际上可能永远不会出现在客户或面向用户的情况中,但它应该受到保护,以便它所代表的关系不会随着时间而改变。
来自2012年热门婴儿名字页面的图片来源: