为什么实际开发中不使用外键
背景
上学的时候,大家肯定都学习了数据库相关的课程,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 更新,即为级联更新。外键与级 联更新适用于单机低并发,不适合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风 险;外键影响数据库的插入速度。
其他大佬的看法:
-
业务数据生成顺序,未必一定可以先生成外键的值,再生成明细数据 修数据:应该没有人没修过生产环境的数据吧?有外键约束,修数据就有一些麻烦了 性能和扩展问题:级联控制,在应用层面做,可以降低数据库的压力。因为数据库的资源是有限资源,应用资源是可以通过加机器进行水平扩展的 分库分表的场景,无法使用外键
参考
下一篇:
如何查看端口号是否被占用