简体   繁体   中英

MySQL - clustered index on the “many” side of a “one to many” relationship

I'm sure this is simple stuff to many of you, so I hope you can help easily.

If I have a MySQL table on the "many" side of a "one to many" relationship - like this:

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

Since this table would always be used via a join using ForeignKey, it would seem useful to make ForeignKey a clustered index so that foreign keys would always be sorted adjacently for the same source record. However, ForeignKey is not unique, so I gather that it is either not possible or bad practice to make this a clustered index? If I try and make a composite primary key using (ForeignKey, ThisTableId) to achieve both the useful clustering and uniqueness, then there is an error "There can only be one auto column and it must be defined as a key".

I think perhaps I am approaching this incorrectly, in which case, what would be the best way to index the above table for maximum speed?

InnoDB requires that if you have an auto-increment column, it must be the first column in a key.

So you can't define the primary key as (ForeignKey, ThisTableId) -- if ThisTableId is auto-increment.

You could do it if ThisTableId were just a regular column (not auto-increment), but then you would be responsible for assigning a value that is at least unique among other rows with the same value in ForeignKey.

One method I have seen used is to make the column BIGINT UNSIGNED, and use a BEFORE INSERT trigger to assign the column a value from the function UUID_SHORT().


@ypercube correctly points out another solution: The InnoDB rule is that the auto-increment column should be the first column of some key, and if you create a normal secondary key, that's sufficient. This allows you to create a table like the following:

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

And the auto-increment works as expected:

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM