我在大学时上数据库的课程,学的三个范式中有个第三范式就是专指的外键约束。可是出来工作以后第一次做数据库表设计的时候,组长大佬却让我在数据库中不要使用外键,改在代码中做相应处理。说得专业点,就是不要在数据库中使用物理外键,改为使用逻辑外键,即在代码中写相关的逻辑代替外键所起的作用。我从此便懂得了,解决实际的问题要从实际出发,不能照本宣科。
外键的作用
1.外键能保证数据的完整性。在没有外键的情况下,数据库就不能强制进行引用完整性检查,如果在高一层没有进行正确的处理,则可能会导致数据出现不一致的情况。
2.外键能使表之间的关系变得清晰。如果数据库中缺少外键,不了解表之间关系的人很难找到正确的关联表,这样可能会导致严重的数据库查询问题(关联错表、查错表)。
为什么数据库可以没有外键
既然外键有那么多好处,为什么这里说设计数据库的时候可以不要外键呢,想作死嘛?但是世事无绝对的,这个世界也不是非黑即白的,很多时候人生只能随波逐流,跟着环境改变。意思就是说,数据库设计还是要根据实际情况,其实有7个理由可以说明为什么数据库可以没有外键。
1.提高性能
在表上拥有活动的外键可以提高数据的质量,但是会影响插入、更新和删除操作的性能。因为在这些操作任务之前,数据库需要检查它是否违反数据完整性。这就是为什么一些架构师和DBA完全放弃外键的原因。数据仓库和分析数据库尤其如此,这些数据仓库和分析数据库不以业务方法(一次一行)处理数据,而是批量处理数据。性能是数据仓库和商业智能的一切。
2.方便旧数据的导入
许多数据库在设计的时候需要考虑导入来自旧数据库的数据的因素。这些数据可能对数据的质量和完整性没有那么严格,为了能够容纳旧的脏数据,架构师有两个选择,一是清理和转换旧的历史遗留数据(昂贵代价,需要人工去编制数据);二是放弃在数据库级别上强制执行参照完整性。哪个方法更好更节约成本更高效,我相信已经不言而喻了。
3.方便全表的重新加载
一些数据库,如数据仓库,分段或接口数据库,需要经常从外部重新加载数据。就像你本地的测试数据库需要从生产环境的正式数据库重新加载数据一样。这可能会导致重新加载数据时数据不一致(在父表为空的情况下,子表可能已经装满)。虽然可以通过在重新加载数据的时候禁用外键来绕过这个问题,然而这却引入了额外的逻辑和复杂性,以及另一个失败点,对性能有负面影响。
4.将外键起的作用交给更高层次的框架完成
一些应用程序使用编程框架,在物理数据库之上创建另一个逻辑层,开发人员不需要编写插入或更新语句来修改数据,而是调用提供的API在后台执行所有操作。ORM(对象关系映射)框架比如Hibernate就是这种情况,这些框架负责维护参照完整性,并与RDBMS一起创建更高级别的数据库引擎。
5.方便跨数据库
在一些大型系统,可能会有很多个数据库。比如说A表在A数据库,B表在B数据库,你想在A表和B表之间创建外键是不可能的。当然你可能会说A表和B表要创建外键就把A表和B表放在一个数据库里面啊,但是我偏不,嘿嘿。
6.节约一些工作成本(偷懒/提高效率)
在创建数据库的时候,如果要存储数据,最低限度是要创建一些表和一些字段。但是创建一些保证数据一致性的结构却不是必须的工作,比如外键等约束。这些工作需要人力和时间成本,但是却没有带来直接的好处。因此很多架构师和DBA都选择忽略掉这一部分。
7.让你在团队里变得不可替代
在现实的社会中,很多人都希望被需要和不可被替代。如果数据库表的设计者是你且只有你,那么表之间的关系就只有你知道,别人要知道表之间的关系就只能通过你,你就变成了不可替代的那个人了。当然在现实中是不可能的,数据库设计都是要留存的,比如说PDM;你也不可能成为不被替代的那个人。没有错,现实就是那么残酷。
"世界上没有谁是不可替代的,一个人离开了,马上就会有另外一个人取代他的位置。"