大家好,我是编程小6,很高兴遇见你,有问题可以及时留言哦。
马基雅维利表示:目的是证明手段正确性的唯一标志。
对于程序员而言,现实同样如此。完成一个任务的方法路径可能有很多,不同的技术都可以实现相应的目标,有的人擅长Java,有的人擅长Python,有的人擅长C++,最终都能解决问题,达到需求方提出的目标。
在数据库设计方面,同样也是如此,今天我们来讨论一个问题,在做数据库表结束设计的时候,要不要设计外键。
对于某些互联网公司来讲,设计外键是明确写在编程手册中的禁止行为。比如说阿里就明确表示:
【强制】不得使用外键与级联,一切外键概念必须在应用层解决。
那么为什么阿里要做这个规定呢?原因在于,外键这个设置的存在,在保证了数据完整性和一致性的同时,会带来很多性能和使用上的问题。
首先我们来看一看外键约束是什么。
外键的意义是如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键。由此可见,外键表示了两个关系之间的相关联系。
比如说,如果一个表为教师表,另一个表为课程表,课程表中主键为课程ID,其中有一个字段是任课教师,那么将这个字段约束为教师表的外键约束,就可以达到,如果设置一个教师表中不存在的教师,那么就会报错。表示如果强制设置一个不存在的教师的话,数据库就会报错。这样就保证了数据库的完整性和一致性。而且在级联删除里,比如说这个教师灭失了,那么删除这个教师的时候,同时也把这个教师任教的课程也删除了。
这样的好处是显而易见的,可以将数据完整性判断交付给数据库,减少了程序员的代码量。
但是,同时外键约束也存在很多缺点,尤其在互联网高并发的场景下。会出现严重的性能问题,因为每次插入数据的时候,数据库会去关联表中查询是否存在相应的数据,即使数据在逻辑上来说是必然存在的。这样的操作其实就是冗余的。
另外,外键约束也有可能导致死锁问题。当数据需要校验并且在事务的处理中存在未完成的情况,或其它一些场景时,就会出现死锁问题,而这类问题,在测试中是基本无法发现的。而在线上产品出现时,会导致很多问题。
除此之外,外键约束也会导致在需要分库分表的时候,带来非常多的额外困难。
基于以上这些问题,很多公司在编程规范中,都会明文规定不得使用外键,将数据完整性和一致性的校验放置到业务逻辑层去完成。尤其是对于一些新的业务,表结构可能随时会发生变化的情况下,使用外键会导致非常多意想不到的问题。
那么,是不是外键就完全是数据库提供的一个鸡肋功能呢?其实也不是这样的。在一些对于数据的完整性要求强烈,而用户量又不是很多的场景,比较说某些管理机构的内部管理系统,在数据表非常明确,比如说社保局,业务一直很稳定,而对于数据逻辑特别敏感,不能出现一个并不存在于辖区的的人申领社保,而依靠程序员的个人素养将数据校验放在逻辑层并不可靠的情况下。就可以使用外键。
总之,各类技术无所谓好与坏,关键在于是否用对了场景。