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.
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
. I would like to create a PRIMARY KEY
as (a, b, id)
but it is not allowed by definition. 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). I verified it. Indeed, with the above PRIMARY KEY (id, a, b)
definition, any query searching for a
does not use any 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)
. 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
!
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:
# 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. 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. If id alone is unique, there's no reason to have a longer primary key.
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.