是否在我的所有表中添加引用?

k0pti3hp  于 2021-06-21  发布在  Mysql
关注(0)|答案(1)|浏览(322)

我有很多这样的table:

CREATE TABLE `name` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `user` INT(11) UNSIGNED NOT NULL REFERENCES users (`id`),
  `user2` INT(11) UNSIGNED NOT NULL REFERENCES users (`id`),
  `data` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

我想知道这个 references users 是一个很好的选择,我应该把它留空,以更快的性能和改进?

db2dz4w8

db2dz4w81#

使用外键与性能关系不大。实际上,这会增加一点开销,因为对表的任何插入或更新都需要验证引用表中是否存在该值。但实际上,这并不比更新索引的开销大多少。
使用外键的原因不是性能,而是为了确保数据的完整性。如果没有外键,对数据库的任何更新都可能会删除数据库中的父行 users 即使有排在 name 那就引用它。没有外键约束,只有您的编码习惯才能保持数据完整。使用外键约束时,删除 users 如果有其他行依赖于它,则返回错误。
这听起来可能是个好主意,但有不同的看法。约束可能会限制您需要执行的某些工作。例如,我和开发人员谈过,他们发现约束会阻碍他们清理格式错误的数据。锁定行为也确实会让您感到惊讶:例如,如果您在 name 将在它引用的行上创建一个锁 users .

/* this also implicitly puts a shared lock on `users` where id = 1234 */ 
UPDATE name SET ... WHERE user = 1234;

不幸的是,mysql的innodb存储引擎不支持您所展示的语法,即声明 REFERENCES 每列定义中的子句。尽管这是标准的sql,但在mysql中是无法识别的。
您会发现,以这种方式定义外键是可以接受的,不会出错,但是它会默默地忽略请求,并且不会实现约束。
innodb只支持表级外键的语法:

CREATE TABLE `name` (
  `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `user` INT(11) UNSIGNED NOT NULL,
  `user2` INT(11) UNSIGNED NOT NULL,
  `data` datetime NOT NULL,
  PRIMARY KEY (`id`),
  FOREIGN KEY (`user`) REFERENCES users (`id`),
  FOREIGN KEY (`user2`) REFERENCES users (`id`)
) ENGINE=InnoDB;

最终的结果是一样的,数据的存储方式和性能影响都是一样的。唯一的区别在于用于定义外键约束的语法。

相关问题