【发布时间】:2019-07-11 12:47:58
【问题描述】:
我有以下一对一的链接表
CREATE TABLE `foo_bar` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`foo_id` int(10) unsigned NOT NULL,
`bar_id` int(10) unsigned NOT NULL,
…
PRIMARY KEY (`id`),
…
) ENGINE=InnoDB
其中foo_id 和bar_id 分别是表foo 和bar 的外键
还有
-
(foo_id, bar_id)上的唯一索引,用于将foo_id的外键映射到 foo 记录,以及查询性能,和… -
bar_id上的唯一索引,用于从bar_id到条形记录的外键映射
请注意,此设置确实允许非唯一的foo_ids,只要它们伴随着唯一的bar_id
我现在想单独在 foo_id 上强制执行唯一性,同时保留 (foo_id, bar_id) 上现有复合索引的性能优势
是否有任何方法可以创建唯一复合索引,其中对引用的列的子集强制执行唯一性,但允许将更多列添加到索引中?
在这个例子中,这看起来像([foo_id], bar_id),其中方括号表示复合索引的唯一部分
我想避免在 (foo_id, bar_id) 上单独索引的开销
在我的脑海中,我想不出任何算法上的原因为什么这是不可能的 - 只要列的唯一子集位于复合索引的开头
注意,我知道我可以使用 foo_id 或 bar_id 作为表的主键,但应用程序需要一个单独的 ID,通过它可以链接记录单独删除,不泄露链接
基本上foo_bar.id 存储在客户端cookie 中(经过可逆加密后),任何个人数据都可以通过此ID 访问。这个想法是,如果客户请求删除,我们删除foo_bar 记录并删除他们的数据,而不破坏foo 和bar 中的匿名或功能数据
这有额外的好处,即使 cookie 在任何地方持续存在,它也将不再可解析为任何数据
【问题讨论】:
-
不要认为至少在 MySQL 中是可能的。但会是一个受欢迎的功能。
-
也许我没有理解正确,但是当您在 bar_id 上已有唯一索引并且希望 foo_id 也唯一时,不需要在 (foo_id, bar_id) 上单独索引.组合的独特性已经得到保证,我怀疑你会遭受严重的性能损失。如果需要,MySQL 还可以合并索引。而且你也可以有“重复”的索引,开销并不像你想象的那么多。我知道,因为我公司的开发人员经常犯这个错误和/或混淆索引和外键。
-
如果你也让
foo_id唯一,那么链接表需要什么?不是主要用于存储一对多或多对多的映射吗? -
" 我知道,因为我公司的开发人员经常犯这个错误和/或混淆索引和外键" @fancyPants 很可能是因为 MySQL 在创建索引时会创建索引外键也... “你也可以有“重复”的索引,开销没有你想象的那么多”这可能会导致优化器选择一个“错误的”索引并且变得更糟选择性能,因为尽量避免制作冗余索引..
-
" MySql 也在外键上创建索引?" 是的,MySQL 可以这样做/这样做.. 见Using FOREIGN KEY Constraints -> "index_name 表示外键 ID . 如果子表上已经有显式定义的索引可以支持外键,则忽略 index_name 值。否则,MySQL 会隐式创建一个外键索引,根据以下规则命名:"跨度>