数据库中为什么不推荐使用外键约束?

文章出处作者:孤独烟 | 微信公众号:打杂的ZRJ

个人觉得这篇文章分析的比较全面,感觉不错。转摘了。

其实这个话题是老生常谈,很多人在工作中确实也不会使用外键。包括在阿里的JAVA规范中也有下面这一条:

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

但是呢,询问他们原因,大多是这么回答的:

每次做DELETE 或者UPDATE都必须考虑外键约束,会导致开发的时候很痛苦,测试数据极为不方便。

坦白说,这么说也是对的。但是呢,不够全面,所以开一文来详细说明。

正文

首先我们明确一点,外键约束是一种约束,这个约束的存在,会保证表间数据的关系“始终完整”。因此,外键约束的存在,并非全然没有优点。比如使用外键,可以:

  • 保证数据的完整性和一致性;

  • 级联操作方便;

  • 将数据完整性判断托付给了数据库完成,减少了程序的代码量;

然而,鱼和熊掌不可兼得。外键是能够保证数据的完整性,但是会给系统带来很多缺陷。正是因为这些缺陷,才导致我们不推荐使用外键,具体如下:

性能问题

假设一张表名为user_tb。那么这张表里有两个外键字段,指向两张表。那么,每次往user_tb表里插入数据,就必须往两个外键对应的表里查询是否有对应数据。如果交由程序控制,这种查询过程就可以控制在我们手里,可以省略一些不必要的查询过程。但是如果由数据库控制,则是必须要去这两张表里判断。

并发问题

在使用外键的情况下,每次修改数据都需要去另外一个表检查数据,需要获取额外的锁。若是在高并发大流量事务场景,使用外键更容易造成死锁。

扩展性问题

这里主要是分为两点:

  • 做平台迁移方便,比如你从Mysql迁移到Oracle,像触发器、外键这种东西,都可以利用框架本身的特性来实现,而不用依赖于数据库本身的特性,做迁移更加方便。

  • 分库分表方便,在水平拆分和分库的情况下,外键是无法生效的。将数据间关系的维护,放入应用程序中,为将来的分库分表省去很多的麻烦。

技术问题

使用外键,其实将应用程序应该执行的判断逻辑转移到了数据库上。那么这意味着一点,数据库的性能开销变大了,那么这就对DBA的要求就更高了。很多中小型公司由于资金问题,并没有聘用专业的DBA,因此他们会选择不用外键,降低数据库的消耗。
相反的,如果该约束逻辑在应用程序中,发现应用服务器性能不够,可以加机器,做水平扩展。如果是在数据库服务器上,数据库服务器会成为性能瓶颈,做水平扩展比较困难。

文章转载自公众号

另一个原因大概是早期的MySQL外键性能比较糟糕,远不如闭源商业数据库软件,也比不上经过优化的应用层约束。现在微服务普及之后就真的没必要了。

 

### 在达梦数据库中修改已存在的约束 在达梦数据库中,直接修改现有的约束是一个常见的操作。通常情况下,如果需要对进行修改,可以先删除原有的约束,然后重新创建新的约束。以下是具体的操作方法: #### 删除现有的约束 要删除现有的约束,可以使用 `ALTER TABLE` 语句中的 `DROP CONSTRAINT` 子句。语法如下: ```sql ALTER TABLE 名 DROP CONSTRAINT 名称; ``` 例如,假设有一个 `employee`,其中包含一个名为 `fk_department_id` 的约束,可以通过以下语句删除该约束[^4]: ```sql ALTER TABLE employee DROP CONSTRAINT fk_department_id; ``` #### 创建新的约束 删除旧的约束后,可以使用 `ALTER TABLE` 语句中的 `ADD CONSTRAINT` 子句来创建一个新的约束。语法如下: ```sql ALTER TABLE 名 ADD CONSTRAINT 名称 FOREIGN KEY (列名) REFERENCES 主名 (主列名); ``` 例如,假设需要在 `employee` 中重新定义一个,将 `department_id` 列关联到 `department` 的 `id` 列,可以执行以下语句: ```sql ALTER TABLE employee ADD CONSTRAINT fk_department_id FOREIGN KEY (department_id) REFERENCES department (id); ``` #### 修改约束的特殊情况 如果仅需要修改的行为(如级联更新或删除),可以通过删除并重新创建的方式来实现。例如,假设需要将的删除行为改为级联删除,可以执行以下操作: 1. 删除现有的约束。 2. 创建新的约束,并指定 `ON DELETE CASCADE`。 示例代码如下: ```sql -- 删除现有 ALTER TABLE employee DROP CONSTRAINT fk_department_id; -- 创建新的,指定级联删除 ALTER TABLE employee ADD CONSTRAINT fk_department_id FOREIGN KEY (department_id) REFERENCES department (id) ON DELETE CASCADE; ``` --- ### 注意事项 - 在删除和重新创建时,确保数据的一致性,避免因约束的临时缺失导致数据异常。 - 如果约束涉及大量数据,建议在低峰时段执行相关操作以减少对系统性能的影响。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值