为什么实际开发中不使用外键

背景

上学的时候,大家肯定都学习了数据库相关的课程,MySQL和Oracle中都有外键。但是自从开始工作,我就发现一个奇怪的问题,企业实际开发中,表结构定义都不会用数据库的外键,当需要用外键做关联的时候,也是仅对字段进行冗余存储,不会用foreign key的定义,究竟有哪些考量呢?此篇做个总结。

外键

什么是外键

两张表有关联关系,才会涉及外键的概念。举例 商品表(商品id、商品名称),订单表(订单id、商品id)。对于订单表来说,商品id就是外键。

外键的作用

CREATE TABLE `commodity` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '商品id',
  `name` varchar(256)  NOT NULL COMMENT '商品名称',
   PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';
CREATE TABLE `order` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '订单id',
  `commodity_id` bigint(20) unsigned NOT NULL COMMENT '商品id',
  PRIMARY KEY (`id`),
  KEY `commodity_id` (`commodity_id`),
  CONSTRAINT `fk_commodity_id` FOREIGN KEY (`commodity_id`) REFERENCES `commodity` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

1. 当我们使用foreign key定义时,会发生什么呢?

  • order表insert数据时,commodity_id必须是commodity已存在的id
  • commodity表delete数据时,要先删除order表中引用commodity.id的数据

2. 外键有啥作用呢?官方说法是,外键可以保证数据的完整性和一致性。 如何保证呢?——级联

删除commodity表数据时,会自动删除order表的关联数据


为什么不用外键

先来瞧瞧阿里的开发手册怎么说:

【强制】不得使用外键与级联,一切外键概念必须在应用层解决。

  说明: 以学生和成绩的关系为例,学生表中的 student_id 是主键,那么成绩表中的 student_id 则为外键。如果更新学生表中的 student_id,同时触发成绩表中的 student_id 更新,即为级联更新。外键与级 联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风 险;外键影响数据库的插入速度。

其他大佬的看法:

  • 业务数据生成顺序,未必一定可以先生成外键的值,再生成明细数据
  • 修数据:应该没有人没修过生产环境的数据吧?有外键约束,修数据就有一些麻烦了
  • 性能和扩展问题:级联控制,在应用层面做,可以降低数据库的压力。因为数据库的资源是有限资源,应用资源是可以通过加机器进行水平扩展的
  • 分库分表的场景,无法使用外键

参考

mysql foreign key(外键) 说明与实例

mysql 外键(foreign key)的详解和实例

外键约束

数据库(外键及其约束理解)

【原创】数据库中为什么不推荐使用外键约束

是否有必要使用外键?为什么不用外键?

猜你喜欢

转载自blog.csdn.net/yxz8102/article/details/107303975