mysql - 在我的所有表格中添加或不添加引用?
问题描述
我有很多这样的表:
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
是否是一个不错的选择,我应该将其留空以加快性能和改进吗?
解决方案
使用外键与性能关系不大。事实上,它可能会增加一点开销,因为对表的任何插入或更新都需要验证该值是否存在于引用的表中。但在实践中,这并不比更新索引多多少开销。
使用外键的原因不是性能,而是为了确保数据完整性。如果没有外键,对数据库的任何更新都可能会删除父行,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;
在数据存储方式和性能影响方面,最终结果是相同的。唯一的区别在于用于定义外键约束的语法。
推荐阅读
- windows - 尝试远程连接 Postgresql(Windows 操作系统)
- spring - JPA 规范按原生 SQL 字段排序
- python - 熊猫,数以百万计
- ios - Realm iOS - 如何更新列表?
- ios - 使用 CoreData 的 SwiftUI 应用程序因 NSInternalInconsistencyException 而崩溃
- python - 如何知道beautifulsoup中网页抓取的最后一个页码网站?
- c# - Elasticsearch.NET 中的复合查询
- python - 数据框如何在给定列中找到字符串时添加特定行
- swift - 自定义 UISegmentedControl
- javascript - 不需要时触发 CSS 翻译事件侦听器的解决方法