业务主键(自然主键):在数据库表中把具有业务逻辑含义的字段作为主键,称为“自然主键(Natural Key)”。

逻辑主键(代理主键):在数据库表中采用一个与当前表中逻辑信息无关的字段作为其主键,称为“代理主键”。

复合主键(联合主键):通过两个或者多个字段的组合作为主键。

原理分析:

使用逻辑主键的主要原因是,业务主键一旦改变则系统中关联该主键的部分的修改将会是不可避免的,并且引用越多改动越大。而使用逻辑主键则只需要修改相应的业务主键相关的业务逻辑即可,减少了因为业务主键相关改变对系统的影响范围。业务逻辑的改变是不可避免的,因为“永远不变的是变化”,没有任何一个公司是一成不变的,没有任何一个业务是永远不变的。最典型的例子就是身份证升位和驾驶执照号换用身份证号的业务变更。而且现实中也确实出现了身份证号码重复的情况,这样如果用身份证号码作为主键也带来了难以处理的情况。当然应对改变,可以有很多解决方案,方案之一是做一新系统与时俱进,这对软件公司来说确实是件好事。

使用逻辑主键的另外一个原因是,业务主键过大,不利于传输、处理和存储。我认为一般如果业务主键超过8字节就应该考虑使用逻辑主键了,因为int是4字节的,bigint是8字节的,而业务主键一般是字符串,同样是 8 字节的 bigint 和 8 字节的字符串在传输和处理上自然是 bigint 效率更高一些。想象一下 code == "12345678" 和 id == 12345678 的汇编码的不同就知道了。当然逻辑主键不一定是 int 或者 bigint ,而业务主键也不一定是字符串也可以是 int 或 datetime 等类型,同时传输的也不一定就是主键,这个就要具体分析了,但是原理类似,这里只是讨论通常情况。同时如果其他表需要引用该主键的话,也需要存储该主键,那么这个存储空间的开销也是不一样的。而且这些表的这个引用字段通常就是外键,或者通常也会建索引方便查找,这样也会造成存储空间的开销的不同,这也是需要具体分析的。

使用逻辑主键的再一个原因是,使用 int 或者 bigint 作为外键进行联接查询,性能会比以字符串作为外键进行联接查询快。原理和上面的类似,这里不再重复。

使用逻辑主键的再一个原因是,存在用户或维护人员误录入数据到业务主键中的问题。例如错把 RMB 录入为 RXB ,相关的引用都是引用了错误的数据,一旦需要修改则非常麻烦。如果使用逻辑主键则问题很好解决,如果使用业务主键则会影响到其他表的外键数据,当然也可以通过级联更新方式解决,但是不是所有都能级联得了的。

使用业务主键的主要原因是,增加逻辑主键就是增加了一个业务无关的字段,而用户通常都是对于业务相关的字段进行查找(比如员工的工号,书本的 ISBN No. ),这样我们除了为逻辑主键加索引,还必须为这些业务字段加索引,这样数据库的性能就会下降,而且也增加了存储空间的开销。所以对于业务上确实不常改变的基础数据而言,使用业务主键不失是一个比较好的选择。另一方面,对于基础数据而言,一般的增、删、改都比较少,所以这部分的开销也不会太多,而如果这时候对于业务逻辑的改变有担忧的话,也是可以考虑使用逻辑主键的,这就需要具体问题具体分析了。

使用业务主键的另外一个原因是,对于用户操作而言,都是通过业务字段进行的,所以在这些情况下,如果使用逻辑主键的话,必须要多做一次映射转换的动作。我认为这种担心是多余的,直接使用业务主键查询就能得到结果,根本不用管逻辑主键,除非业务主键本身就不唯一。另外,如果在设计的时候就考虑使用逻辑主键的话,编码的时候也是会以主键为主进行处理的,在系统内部传输、处理和存储都是相同的主键,不存在转换问题。除非现有系统是使用业务主键,要把现有系统改成使用逻辑主键,这种情况才会存在转换问题。暂时没有想到还有什么场景是存在这样的转换的。

使用业务主键的再一个原因是,对于银行系统而言安全性比性能更加重要,这时候就会考虑使用业务主键,既可以作为主键也可以作为冗余数据,避免因为使用逻辑主键带来的关联丢失问题。如果由于某种原因导致主表和子表关联关系丢失的话,银行可是会面临无法挽回的损失的。为了杜绝这种情况的发生,业务主键需要在重要的表中有冗余存在,这种情况最好的处理方式就是直接使用业务主键了。例如身份证号、存折号、卡号等。所以通常银行系统都要求使用业务主键,这个需求并不是出于性能的考虑而是出于安全性的考虑。

使用复合主键的主要原因和使用业务主键是相关的,通常业务主键只使用一个字段不能解决问题,那就只能使用多个字段了。例如使用姓名字段不够用了,再加个生日字段。这种使用复合主键方式效率非常低,主要原因和上面对于较大的业务主键的情况类似。另外如果其他表要与该表关联则需要引用复合主键的所有字段,这就不单纯是性能问题了,还有存储空间的问题了,当然你也可以认为这是合理的数据冗余,方便查询,但是感觉有点得不偿失。

使用复合主键的另外一个原因是,对于关系表来说必须关联两个实体表的主键,才能表示它们之间的关系,那么可以把这两个主键联合组成复合主键即可。如果两个实体存在多个关系,可以再加一个顺序字段联合组成复合主键,但是这样就会引入业务主键的弊端。当然也可以另外对这个关系表添加一个逻辑主键,避免了业务主键的弊端,同时也方便其他表对它的引用。

综合来说,网上大多数人是倾向于用逻辑主键的,而对于实体表用复合主键方式的应该没有多少人认同。支持业务主键的人通常有种误解,认为逻辑主键必须对用户来说有意义,其实逻辑主键只是系统内部使用的,对用户来说是无需知道的。

结论或推论:

1、尽量避免使用业务主键,尽量使用逻辑主键。

2、如果要使用业务主键必须保证业务主键相关的业务逻辑改变的概率为0,并且业务主键不太大,并且业务主键不能交由用户修改。

3、除关系表外,尽量不使用复合主键。

使用逻辑主键的最佳实践指南:

1、足够用就好。系统使用的生命周期以100年为限,逻辑主键数据类型采用下表规则,如果不确定则使用int类型。

数据量 数据类型 数据大小 生成频率 备注
< 128 tinyint 1 字节 1条/年 频率过低,不太靠谱,不建议采用
< 3 万 smallint 2 字节 27条/月 频率较低,慎用
< 21 亿 int 4 字节 40条/分钟 能满足大部分情况
< 922 亿亿 bigint 8 字节 292万条/毫秒 能满足绝大部分情况 
>= 922 亿亿 uniqueidentifier 16 字节

100亿用户同时每毫秒生成10亿条,可以连续生成10亿年

可用于分布式、高并发的应用

2、一般采用自增长方式或NewID()方式。

3、主键字段名称一般采用“表名ID”方式,方便识别和表联接。

4、如果表存在分布式应用,则可以考虑采用不同起始值,相同步长方式自增。例如有3个部署在不同地方的库,则可以如下设计:

起始值 步长
1 10
2 10
3 10

步长统一设置10是为了方便日后扩展,这样不同库之间也能保持主键唯一性了,也方便合并。

5、如果存在高并发性需求或数据表迁移需求,可以考虑使用uniqueidentifier类型,并使用NewID()函数。

6、可以考虑对业务主键建立唯一性索引,以实现业务主键唯一性的业务需求。

7、如果需要考虑业务主键的性能需求,可以把业务主键建立聚集索引,而逻辑主键只建立主键约束和非聚集索引即可。

8、关系表可以考虑采用复合主键方式,复合主键不用于实体表。

关于业务主键和逻辑主键相关推荐

  1. 什么是逻辑主键和业务主键

    定义: 逻辑主键(surrogate key):无意义的字段,即自增长字段,即identity.这其中还有一个选择GUID(Globally Unique Identifier).  也叫代理主键. ...

  2. 对逻辑主键、业务主键和复合主键的思考

    这几天对逻辑主键.业务主键和复合主键进行了一些思考,也在网上搜索了一下相关的讨论,相关讨论可以看最下面的参考链接.下面是自己基于 SQL Server 做的一些总结,其他数据库(Oracle.MySQ ...

  3. 主键的选择,应该是业务有意义还是业务无意义,应该是逻辑主键还是业务主键

    主键的选择,应该是业务有意义还是业务无意义,应该是逻辑主键还是业务主键呢?我发现有很多支持主键应该都是无意义的,不要和业务相关.我很疑惑,疑惑为什么说应该 无意义呢,这个应该无意义有什么根据呢? 首先 ...

  4. mysql主主同步冲突_MySQL主主同步主键冲突处理

    两台数据库都报slave同步失败了,先说明一下环境,架构:lvs+keepalived+amoeba+mysql,主主复制,单台写入, 主1:192.168.0.223(写) 主2:192.168.0 ...

  5. 2019-7-27 [MySQL] DQL 简单查询[别名/去重/运算] 条件查询 排序查询 聚合查询 分组查询 导出与导入 多表操作[一对多/多对多][创外键 创联合主键 约束 添加 删除 测试]

    文章目录 5 SQL语句(DQL) 5.1DQL准备工作和语法 5.1.1准备工作 5.1.2 DQL语法: 5.2 简单查询 5.2.1 查询所有的商品 5.2.2 查询商品名和商品价格. 5.2. ...

  6. mysql 联合主键重复数据库_联合主键和复合主键有什么区别

    联合主键和复合主键有什么区别 发布时间:2020-07-11 09:52:20 来源:亿速云 阅读:171 作者:Leah 这期内容当中小编将会给大家带来有关联合主键和复合主键有什么区别,文章内容丰富 ...

  7. mysql复合主键优缺点_提问关于 mysql得联合主键和复合主键的问题

    这个问题要是问外国开发者,TA们能一脸懵逼. 在英文语境中只有 Composite Primary Key(也有叫 Compound Primary Key 的),就是一个表中如果是多个字段组成一个主 ...

  8. mysql主键能当外键吗_MySQL主键跟外键

    定义主键和外键主要是为了维护关系数据库的完整性,总结一下:1.主键是能确定一条记录的唯一标识,比如,一条记录包括身份正号,姓名,年龄. 身份证号是唯一能确定你这个人的,其他都可能有重复,所以,身份证号 ...

  9. mysql联合主键语句6_初探SQL语句复合主键与联合主键

    一.复合主键 所谓的复合主键 就是指你表的主键含有一个以上的字段组成,不使用无业务含义的自增id作为主键. 比如 create table test ( name varchar(19), id nu ...

最新文章

  1. 理解 Delphi 的类(十) - 深入方法[28] - 递归函数实例: 搜索当前目录下的所有嵌套目录...
  2. 图解Oracle 12c 安装示例数据库
  3. jQuery图片轮播特效
  4. 鸟哥的Linux私房菜(服务器)- 第五章、 Linux 常用网络指令
  5. Reflector for .NET
  6. 奇奇怪怪的知识增加了,大括号的历史你知道吗?
  7. google官方上拉刷新
  8. vue 项目常见功能(搜索 时间戳转换 过滤器)
  9. Java基础之路--引用数据类型之数组
  10. Spring mvc 中 DispatcherServlet 的学习和理解
  11. c#控制台模拟dos_超好用的C#控制台应用模板
  12. 从Anker到SHEIN,对不起我要放弃Amazon了
  13. Qt设计一个给图像打掩膜的界面
  14. Android系统日历读取各厂商农历年重复event
  15. 【论文review+总结】屏幕内容图像质量评估SC-IQA(Screen Content Image Quality Assessment)
  16. phpbreak跳出几层循环_PHP break:跳出循环
  17. [笔记][java 4 android] [028~034]接口、异常和I/O流
  18. 浅谈FRVT人脸识别测评
  19. Android 仿微博的点赞上报功能,持续点赞再取消
  20. 计算机结构实验三,计算机体系结构实验报告——实验三.pdf

热门文章

  1. Oracle 12c数据库优化器统计信息收集的最佳实践
  2. 最大回撤线性算法实现
  3. 2023年科普新书大盘点:重磅新书,值得期待!
  4. 关于新书《修炼之道:.NET开发要点精讲》的各种说明
  5. #JavaScript JQuery 实现新用户注册
  6. storm-tuple(1)
  7. windows10下载链接
  8. Ubuntu18.04配置双网卡上网
  9. windows 可以禁用的服务盘点
  10. 【学者风采】Cong Wang(王聪)