【问题标题】:MySQL - clustered index on the "many" side of a "one to many" relationshipMySQL - “一对多”关系的“多”端的聚集索引
【发布时间】:2014-09-29 15:40:59
【问题描述】:

我相信这对你们中的许多人来说都很简单,所以我希望你们能轻松地提供帮助。

如果我在“一对多”关系的“多”端有一个 MySQL 表 - 像这样:

Create Table MyTable(
ThisTableId int auto_increment not null,
ForeignKey int not null,
Information text
)

由于该表总是通过使用 ForeignKey 的连接来使用,因此将 ForeignKey 设置为聚集索引似乎很有用,这样外键对于相同的源记录总是被相邻排序。但是,ForeignKey 不是唯一的,所以我认为将其设为聚集索引是不可能或不好的做法?如果我尝试使用 (ForeignKey, ThisTableId) 创建复合主键来实现有用的集群和唯一性,则会出现错误“只能有一个自动列,并且必须将其定义为键”。

我想我可能是在错误地处理这个问题,在这种情况下,索引上表以获得最大速度的最佳方法是什么?

【问题讨论】:

  • 我怀疑你过早地过度优化你的数据结构。 ForeignKey 上的索引应该没问题。 ThisTableId 应声明为 primary key

标签: mysql sql indexing


【解决方案1】:

InnoDB 要求,如果你有一个自增列,它必须是键中的 first 列。

所以你不能将主键定义为 (ForeignKey, ThisTableId) -- 如果 ThisTableId 是自增的。

如果 ThisTableId 只是一个常规列(不是自动增量),您可以这样做,但是您将负责分配一个值,该值在 ForeignKey 中具有相同值的其他行中至少是唯一的。

我见过的一种方法是使列 BIGINT UNSIGNED,并使用 BEFORE INSERT 触发器为该列分配来自函数 UUID_SHORT() 的值。


@ypercube 正确地指出了另一个解决方案:InnoDB 规则是自动增量列应该是 some 键的第一列,如果您创建一个普通的辅助键,那就足够了。这允许您创建如下表:

CREATE TABLE `MyTable` (
  `ForeignKey` int(11) NOT NULL,
  `ThisTableId` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`ForeignKey`,`ThisTableId`),
  KEY (`ThisTableId`)
) ENGINE=InnoDB;

自动增量按预期工作:

mysql> INSERT INTO MyTable (ForeignKey) VALUES (123), (234), (345), (456);

mysql> select * from MyTable;
+------------+-------------+
| ForeignKey | ThisTableId |
+------------+-------------+
|        123 |           1 |
|        234 |           2 |
|        345 |           3 |
|        456 |           4 |
+------------+-------------+

【讨论】:

  • 但您也可以将 (ForeignKey, ThisTableId) 作为 PK 并在 (ThisTableId) 中使用唯一(或简单)键 - 并且在 ThisTableId 中仍然具有自动增量属性。对吗?
  • @ypercube,实际上,你是对的。这是我忽略的一点。我将编辑以上内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-26
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多