简体   繁体   English

在 AUTO_INCREMENT 列中使用 UNIQUE 来创建改进的 PRIMARY KEY

[英]Use UNIQUE in AUTO_INCREMENT column to create an improved PRIMARY KEY

Taking into account that in MySQL the AUTO_INCREMENT column must be part of the PRIMARY KEY , I would like to ask if makes sense using UNIQUE key in that AUTO_INCREMENT column to be able to create a composite PRIMARY KEY without defining it as the first PK index.考虑到在 MySQL 中AUTO_INCREMENT列必须是PRIMARY KEY一部分,我想问一下在该AUTO_INCREMENT列中使用UNIQUE键是否能够创建复合PRIMARY KEY而不将其定义为第一个PK 索引是否有意义。

I created a table like this:我创建了一个这样的表:

CREATE TABLE `test` (
id INT NOT NULL auto_increment,
a  INT NOT NULL,
b  INT NOT NULL,
c  INT NOT NULL,
PRIMARY KEY (id, a, b));

My purpose is to search by (a) or (a, b) and then sort it according to id .我的目的是按(a)(a, b) ,然后根据id对其进行排序。 I would like to create a PRIMARY KEY as (a, b, id) but it is not allowed by definition.我想创建一个PRIMARY KEY作为(a, b, id)但定义不允许。 Besides, as documentation states, a PRIMARY KEY composed of (x, y, z) will take advantage of PRIMARY KEY only if you search by (x) , (x, y) or (x, y, z) , but not if you search by (y) or (y , z) (or anything else).此外,由于文档状态,一个PRIMARY KEY组成(x, y, z)将利用PRIMARY KEY只有当你通过搜索(x) (x, y)(x, y, z)但如果您通过(y)(y , z) (或其他任何内容)进行搜索。 I verified it.我验证过了。 Indeed, with the above PRIMARY KEY (id, a, b) definition, any query searching for a does not use any PRIMARY KEY :事实上,根据上述PRIMARY KEY (id, a, b)定义,任何搜索a查询都不使用任何PRIMARY KEY

DESCRIBE SELECT `a`, `b` FROM `test` WHERE `a` = 0;
+------+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id   | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+------+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|    1 | SIMPLE      | test  | index | NULL          | PRIMARY | 12      | NULL |    1 | Using where; Using index |
+------+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+

I decided to cheat a bit and redefined id as UNIQUE KEY (so that it is still regarded as a KEY ) and then recreated a PRIMARY KEY as (a, b, id) .我决定作弊并将id重新定义为UNIQUE KEY (因此它仍然被视为KEY ),然后重新创建一个PRIMARY KEY作为(a, b, id) This works:这有效:

ALTER TABLE `test` DROP PRIMARY KEY, ADD UNIQUE KEY (`id`), ADD PRIMARY KEY (`a`, `b`, `id`)

Now, searching by a uses PRIMARY KEY !现在,按a搜索使用PRIMARY KEY

DESCRIBE SELECT `a`, `b` FROM `test` WHERE `a` = 0;
+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
| id   | select_type | table | type | possible_keys | key     | key_len | ref   | rows | Extra       |
+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+
|    1 | SIMPLE      | test  | ref  | PRIMARY       | PRIMARY | 4       | const |    1 | Using index |
+------+-------------+-------+------+---------------+---------+---------+-------+------+-------------+

That changes this original PRIMARY KEY (id, a, b) with id in the first position to another scheme with a in the first position:这会将id在第一个位置的原始PRIMARY KEY (id, a, b)更改为另一个在第一个位置具有a方案:

# before
SHOW KEYS FROM `test`;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test  |          0 | PRIMARY  |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| test  |          0 | PRIMARY  |            2 | a           | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| test  |          0 | PRIMARY  |            3 | b           | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

# after
SHOW KEYS FROM `test`;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| test  |          0 | PRIMARY  |            1 | a           | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| test  |          0 | PRIMARY  |            2 | b           | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| test  |          0 | PRIMARY  |            3 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
| test  |          0 | id       |            1 | id          | A         |           0 |     NULL | NULL   |      | BTREE      |         |               |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

Does this have any performance penalties or any disadvantages I did not see?这是否有任何性能损失或我没有看到的任何缺点? This solutions looks to me simpler than triggering stored procedures to increment the index (like this solution ).这个解决方案在我看来比触发存储过程来增加索引更简单(就像这个解决方案)。

Thank you in advance先感谢您

It seems like you can achieve your goals by having id as the sole primary key and indexes on (a,b) and (a) - recent versions of mysql will implicitly add the primary key to the end of all other indexes.似乎您可以通过将 id 作为唯一主键和 (a,b) 和 (a) 上的索引来实现您的目标 - 最近版本的 mysql 会隐式地将主键添加到所有其他索引的末尾。 To avoid a separate sort step, you may need to hint your a= query to use the a index instead of the a,b index.为避免单独的排序步骤,您可能需要提示 a= 查询使用 a 索引而不是 a,b 索引。 If id alone is unique, there's no reason to have a longer primary key.如果 id 本身是唯一的,则没有理由拥有更长的主键。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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