主键类型
所有数据库表必须具有一个主键列。 主键唯一地标识表中的一行,因此它受到以下约束的约束:
- 独特
- 非空
- 不可变的
选择主键时,我们必须考虑以下方面:
- 主键可用于通过外键关系连接其他表
- 主键通常具有关联的默认索引,因此数据类型越紧凑,索引将占用的空间越少
- 一个简单的键比一个复合键的性能更好
- 即使在高度并发的环境中,主键分配也必须确保唯一性
选择主键生成器策略时,选项为:
- 自然键,使用保证单个行唯一性的列组合
- 替代键,独立于当前行数据生成
自然键
自然钥匙的唯一性受外部因素(例如,人的唯一标识符,社会保险号,车辆识别号)的影响。
自然键很方便,因为它们具有与外界等效的功能,并且不需要任何额外的数据库处理。 因此,即使在将实际行插入数据库之前,我们也可以知道主键,从而简化了批量插入操作。
如果自然键是单个数字值,则性能可与替代键的性能相媲美。
对于复合键,我们必须意识到可能的性能损失:
- 复合键联接比单键联接慢
- 复合键索引比单键索引需要更多空间
对于索引和连接,非数字键的效率低于数字键(整数,bigint)。 CHAR(17)自然密钥(例如,车辆识别号)占用17个字节,而不是4个字节(32位整数)或8个字节(64位bigint)。
最初的模式设计唯一性假设可能不会永远成立。 假设我们使用了一个特定的国家/地区公民数字代码来标识所有应用程序用户。 如果现在我们需要支持其他没有此类公民数字代码或现有条目相互冲突的国家,那么我们可以得出结论,架构的发展可能受到阻碍。
如果自然键唯一性约束发生变化,将很难同时更新主键(如果我们仍然设法删除了主键约束)和所有关联的外键关系。
代理键
代理键是独立于当前行数据而生成的,因此其他列约束可以根据应用程序业务需求自由发展。
数据库系统可以管理代理密钥的生成,并且密钥通常是数字类型(例如,整数或bigint),每当需要新密钥时就递增。
如果我们想控制代理密钥的生成,我们可以使用128位GUID或UUID 。 由于不再需要额外的数据库密钥生成处理,因此简化了批处理并可以提高插入性能。 即使未广泛采用此策略,在设计数据库模型时也值得考虑 。
当数据库标识符生成责任落在数据库系统上时,有几种策略可以自动增加代理键:
数据库引擎 | 自动递增策略 |
---|---|
甲骨文 | 序列 |
微软SQL | 身份 顺序 |
PostgreSQL的 | 序列 , 串行类型 |
的MySQL | 自动递增 |
DB2 | 身份 顺序 |
数据库 | 身份 顺序 |
设计方面
- 因为可以从不同的事务中同时调用序列,所以它们通常没有事务。
数据库引擎 引用 甲骨文 生成序列号时,该序列将递增,而与提交或回滚的事务无关 微软SQL 序列号是在当前事务范围之外生成的。 无论使用序列号的事务是已提交还是已回滚,它们都会被消耗 PostgreSQL的 由于序列是非事务性的,因此如果事务回滚,则不会撤消setval所做的更改 - IDENTITY类型是由SQL:2003标准定义的,因此它是标准的主键生成器策略。某些数据库引擎允许您在IDENTITY和SEQUENCE之间进行选择,因此您必须确定哪种更适合您当前的架构要求 。
- 使用IDENTITY生成器策略时, Hibernate禁用JDBC插入批处理 。
翻译自: https://www.javacodegeeks.com/2014/06/database-primary-key-flavors.html