【问题标题】:Can I add a compound unique key if one of the fields is already unique如果其中一个字段已经是唯一的,我可以添加复合唯一键吗
【发布时间】:2017-09-17 17:41:15
【问题描述】:

在 MySQL 中,下面的语句有意义吗?

CREATE TABLE `sku_classification` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `sku` int(10) unsigned NOT NULL,
  `business_classification_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `IDX_SKU_BUSINESS_CLASSIFICATION` (`sku`,`business_classification_id`),
  UNIQUE KEY `sku` (`sku`)
)

在字段组合 (sku,business_classification_id) 上添加唯一键是否不必要的矫枉过正,其中一个字段 (sku) 已经具有唯一索引?或者不是,这种重复的唯一索引确实是有原因的?

【问题讨论】:

  • 一开始你为什么要这样做?
  • @juergen-d 遗留代码。正在考虑是否应该删除它。
  • 第一个唯一键本身将允许多个具有不同分类的相同 sku。第二个将阻止具有相同 sku 的多行,因此它使第一个无关紧要。真正的问题是真正需要什么。是否可以拥有具有不同分类的相同 sku,或者只能有一个具有特定 sku 的行。 IOW,期望的业务逻辑是什么?
  • @SloanThrasher sku 应该是唯一的。所以我猜复合键没有任何区别,应该被删除。
  • 是的。它永远不会发挥作用,因为一个 sku 只允许一行。

标签: mysql schema unique-constraint unique-key unique-index


【解决方案1】:

是的,你可以。但这没有意义。但是,让我们分析一下是怎么回事。

INDEXUNIQUE 与否)是便于在表中查找的 BTree。

UNIQUE 索引既是索引又是“约束”,表示不得有任何重复

你已经说过UNIQUE(sku)。这提供了索引和唯一性约束。

添加UNIQUE(sku, x)按此顺序

  • 不提供任何额外的唯一性约束,
  • 不提供任何额外的索引功能,除了...
  • 确实提供了一个可能有用的“覆盖”索引如果SELECT 中提到的仅有的两列是skux。即便如此,您也可以将其设为 INDEX 而不是 UNIQUE因为...
  • 每个INSERT 都必须做一些额外的努力来防止“重复密钥”。 (好吧,INSERT 代码不够聪明,无法看到您拥有UNIQUE(sku)。)

如果这是您的完整表格,那么没有有充分的理由使用id AUTO_INCREMENT;您不妨将sku 推广为PRIMARY KEY。 (PK 是 UNIQUE KEY。)

此外...另一方面,如果您建议UNIQUE(x, sku),那么会有一点不同。这为您提供了一种通过x 有效查找的方法——xx=constant AND sku BETWEEN ... 的范围,或(sku, x) 未提供的某些其他内容。 索引中的顺序很重要。但是,同样,它也可能是INDEX(x, sku),而不是UNIQUE

因此,表呈现的最佳索引集不是 3 个索引,而是 1 个:

PRIMARY KEY(sku)

另一个注意事项:使用 InnoDB,PK 在 BTree 中与数据“聚集”在一起。也就是说,通过PK查找是非常有效的。当你需要通过一个“二级索引”时,有两个步骤:首先向下钻取二级索引的 BTree 找到 PK,然后向下钻取 PK 的 BTree。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    • 2011-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    相关资源
    最近更新 更多