MySQL中复合聚集索引的实现

MySQL中复合聚集索引的实现,mysql,indexing,query-optimization,Mysql,Indexing,Query Optimization,我需要创建复合聚集索引,比如:用户名、名称、id。实现这样的东西是真的吗?我需要提高查询的性能,比如where username=?名称=?通过在Innodb中使用聚集索引。但我认为它不会起作用,因为我的排名是第三位,而且它不会被使用。定义一个包含多列的聚集索引是可以的 CREATE TABLE mytable ( username VARCHAR(64) NOT NULL, name VARCHAR(64) NOT NULL, id BIGINT PRIMARY KEY (us

我需要创建复合聚集索引,比如:用户名、名称、id。实现这样的东西是真的吗?我需要提高查询的性能,比如where username=?名称=?通过在Innodb中使用聚集索引。但我认为它不会起作用,因为我的排名是第三位,而且它不会被使用。

定义一个包含多列的聚集索引是可以的

CREATE TABLE mytable (
  username VARCHAR(64) NOT NULL,
  name VARCHAR(64) NOT NULL,
  id BIGINT
  PRIMARY KEY (username, name, id)
);
如果查询前两列,它将使用聚集索引,因此可以避免通过二级索引进行查找的开销

但是如果使用EXPLAIN报告优化器的查询计划,您将看到访问是
type:ref
,这意味着索引查找,而不是唯一的索引查找。也就是说,它可能会匹配多行

mysql> explain select * from mytable where username = 'user' and name = 'name';
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------+
| id | select_type | table   | partitions | type | possible_keys | key     | key_len | ref         | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------+
|  1 | SIMPLE      | mytable | NULL       | ref  | PRIMARY       | PRIMARY | 516     | const,const |    1 |   100.00 | NULL  |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------+
在对主键执行查找时,我们希望看到
type:eq\u ref
type:const
,这意味着它正在执行唯一的查找,并且查询保证匹配0或1行

mysql> explain select * from mytable where username = 'user' and name = 'name' and id = 1;
+----+-------------+---------+------------+-------+---------------+---------+---------+-------------------+------+----------+-------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref               | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------------------+------+----------+-------+
|  1 | SIMPLE      | mytable | NULL       | const | PRIMARY       | PRIMARY | 524     | const,const,const |    1 |   100.00 | NULL  |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------------------+------+----------+-------+
两个查询都使用聚集索引


请回复您的评论:


InnoDB要求自动递增列是表中键的第一列。它不必是主键。因此,您可以这样做,例如:

CREATE TABLE `mytable` (
  `username` varchar(64) NOT NULL,
  `name` varchar(64) NOT NULL,
  `id` bigint NOT NULL AUTO_INCREMENT,
  `x` int DEFAULT NULL,
  PRIMARY KEY (`username`,`name`,`id`),
  KEY (`id`)
) ENGINE=InnoDB;

注意,我添加了一个额外的
键(id)
,以满足InnoDB的要求。但是在主键中,
id
仍然在末尾。

当我尝试在InnoDB中添加这样的键时:alter table user drop primary key,add primary key(用户名(12)、密码(4)、id);我收到一个错误:错误代码:1075。表定义不正确;只能有一个自动列,必须将其定义为键InnoDB要求自动递增列为键中的第一列。更正:“InnoDB要求自动递增列为某个键中的第一列。”@NoActualName-不要使用“前缀”(
(12)
,等等)。它破坏了索引的实用性。特别是,它不会超出第一个带前缀的列。请提供您的
创建表
,这样我们就不必在各种边缘情况下跳舞了。