说起来为什么谈到这个话题,其实原因特别简单。在我做毕业设计的时候,我本身再设计表的时候并没有加外键。这是正常的。但是在老师检查的时候,一直在说,一定要有外键约束。不然不符合数据库设计规范。(当然这句话是不对的。)最后强制我在数据库中加了好多条外键。因为在我们日常工作中确实很少用到外键。甚至都不会用。包括在阿里的JAVA开发规范中也有下面这一条
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
但是呢,如果真问一下具体为什么。可能会这么说。
每次做DELETE 或者UPDATE都必须考虑外键约束,会导致开发的时候很痛苦,测试数据极为不方便。
当然,这么说也是对的。但是呢,不够全面,所以我通过正文来进行详细说明。
正文
首先我们明确一点,外键约束是一种约束,这个约束的存在,会保证表间数据的关系“始终完整”。因此,外键约束的存在,并非全然没有优点。
比如使用外键,可以
保证数据的完整性和一致性
级联操作方便
将数据完整性判断托付给了数据库完成,减少了程序的代码量
然而,鱼和熊掌不可兼得。外键是能够保证数据的完整性,但是会给系统带来很多缺陷。正是因为这些缺陷,才导致我们不推荐使用外键,具体如下
性能问题
首先数据库的表上拥有活动的外键确实可以提高数据质量,但插入、更新和删除操作的性能就会被影响。在这些任务之前,数据库需要检查它是否违反数据完整性。这就是为什么一些架构师和DBA完全放弃外键的原因。数据仓库和分析数据库尤其如此,这些数据仓库和分析数据库不以交易方式(一次一行)处理数据,而是批量处理数据。性能是数据仓库和商业智能的一切。
并发问题
使用外键,外键关联的数据查询要去另一张表,获取额外的锁,容易造成死锁。尤其是大型数据库,死锁的可能性更高。
跨数据平台关系
这可能不是数据库没有外键的正确理由,一些数据库跨越更多的物理数据库甚至引擎,并且在技术上可能不能创建跨越数据库的它不能在同一台服务器上的两个数据库上创建key。比如说SQL Server它不能在同一台服务器上的两个数据库上创建key。而且这种架构在大型系统中很常见。
同时为了之后业务可能做平台迁移方便,比如从Oracle迁移到Mysql,像触发器、外键这种东西,都可以利用框架本身的特性来实现,而不用依赖于数据库本身的特性,做迁移更加方便。
能否实现问题
使用外键,其实将应用程序应该执行的判断逻辑转移到了数据库上。那么这意味着一点,数据库的性能开销变大了,那么这就对DBA的要求就更高了。大多数公司并没有MBA,因此会选择不用外键,降低数据库的消耗。
相反的,如果该约束逻辑在应用程序中,发现应用服务器性能不够,可以加机器,做水平扩展。如果是在数据库服务器上,数据库服务器会成为性能瓶颈,做水平扩展比较困难。
所以这就很明白了,外键当然是能不加就不加。并不是非有不可。
关注公众号“薪笙学java”了解更多Java知识。