数据库为什么数据库不应该使用外键( 二 )
- 向 posts 表中插入数据时 , 检查 author_id 是否在 authors 表中存在;
- 修改 posts 表中的数据时 , 检查 author_id 是否在 authors 表中存在;
- 删除 authors 表中的数据时 , 检查 posts 中是否存在引用当前记录的外键;
在这里我们在数据库中同时创建 authors、posts 和 foreign_key_posts 三种表 , 如下所示 , 其中 posts 和 foreign_key_posts 两个表中的列完全相同 , 只是 foreign_key_posts 表为 author_id 字段增加了 RESTRICT 类型的外键约束:
本文插图
图 3 - 外键性能测试关系图
我们先在 authors 表中插入一条记录 , 随后分别在 posts 和 foreign_key_posts中插入多条新数据列引用该条记录 , 前者不会检查外键的合法性 , 而后者会做额外的检查 。 你可以在 这里 找到作者用来测试外键额外开销的 Go 语言代码6 , 经过多次基准测试 , 我们可以得到如下所示的结果:
BenchmarkBaseline-83770309503 ns/opBenchmarkForeignKey-83331317162 ns/opBenchmarkBaseline-83192315506 ns/opBenchmarkForeignKey-83381315577 ns/opBenchmarkBaseline-83298312761 ns/opBenchmarkForeignKey-83829345342 ns/opBenchmarkBaseline-83753291642 ns/opBenchmarkForeignKey-83948325239 ns/op 作者执行了 4 次外键的基准测试 , 虽然 4 次测试的结果不是特别稳定 , 但是使用外键的用例在每次测试中都明显弱于不使用外键的用例 , 外键带来的额外开销分别为 ~2.47%、~0.02%、~10.41% 和 ~11.52% 。 这里的基准测试只是一个比较简单的定量分析 , 但是我们也可以从结果中看到大概的趋势 — 外键的完整性检查确实会带来额外的性能开销 , 而这些开销在高并发的服务中需要慎重考虑 。想要在应用程序中模拟数据库外键的功能其实比较容易 , 我们只需要遵循以下的几个准则:
- 向表中插入数据或者修改表中的数据时 , 都应该执行额外的 SELECT 语句确保它引用的数据在数据库中存在;
- 在删除数据之前需要执行额外的 SELECT 语句检查是否存在当前记录的引用;
BEGINSELECT * FROM authors WHERE id =FOR UPDATE;-- INSERT INTO posts ... / UPDATE posts ...END 但是如果我们要删除 authors 表中的数据 , 就需要查询所有引用 authors 数据的表;如果有 10 个表都有指向 authors 表的外键 , 我们就需要在 10 个表中查询是否存在对应的记录 , 这个过程相对比较麻烦 , 不过也是为了实现完整性的必要代价 , 不过这种模拟外键方法其实远比使用外键更消耗资源 , 它不仅需要查询关联数据 , 还要通过网络发送更多的数据包 。级联操作 当我们在关系型数据库中创建外键约束时 , 如果使用如下所示的 SQL 语句指定更新或者删除记录时使用 CASCADE 行为 , 那么在客户端更新或者删除数据时就会触发级联操作:
ALTER TABLE postsADD CONSTRAINT FOREIGN KEY (author_id)REFERENCES authors(id)ON UPDATE CASCADEON DELETE CASCADE;
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 热量|为什么有的人喝凉水都长肉,有的人却光吃不胖?营养科医生:原因其实很简单
- 『中越战争』1979年的中越战争,为什么世界各国都认为越南会赢?主要的原因其实有3点
- 蜜蜂蜇熊刺针拔不出而被肢解致死
- 三星手机|为什么三星手机,在我国越来越没市场了?原来这是必然结果
- 胖子撩综艺|为什么特斯拉这么受欢迎?自主品牌造不出水平相当的电动汽车吗?
- 不执著财经|为什么越来越多的外企都搬迁到东南亚?
- 罗民教授|看到好多脑梗的病人,而且是正值壮年的男人居多,这是为什么呢?
- 美国得克萨斯州|6岁男孩在校戴耳环被禁,妈妈怒指校方性别歧视:为什么女生就行?
- 娱乐仰望新视角|发动机质量差?,为什么大众车迷说到大众就是说双离合顿挫
- 科技速递|为什么太空中看起来没有引力?
