0

I need to create composit clustered index like: username, name, id. Is it real to implement such thing? I need to boost perfomance of query like where username = ? and name = ? by using clustered indexes in Innodb. But i think it wont work because id stay at 3rd place, and it wont be used.

1 Answer 1

1

It's fine to define a clustered index with multiple columns.

CREATE TABLE mytable (
  username VARCHAR(64) NOT NULL,
  name VARCHAR(64) NOT NULL,
  id BIGINT
  PRIMARY KEY (username, name, id)
);

If you query against the first two columns, it will use the clustered index, so it will avoid the overhead of lookups via secondary indexes.

But if you use EXPLAIN to report the optimizer's plan for the query, you'll see that the access is type: ref which means an index lookup, but not a unique index lookup. That is, it will potentially match multiple rows.

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  |
+----+-------------+---------+------------+------+---------------+---------+---------+-------------+------+----------+-------+

When doing lookups against a PRIMARY KEY, we'd like to see type: eq_ref or type: const which means it is doing a unique lookup, and the query is guaranteed to match either 0 or 1 row.

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  |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------------------+------+----------+-------+

Both queries are using the clustered index.


Re your comment:

InnoDB requires the auto-increment column be the first column of a key in the table. It doesn't have to be the primary key. So you can do this for example:

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;

Notice I added an extra KEY (id) to satisfy InnoDB's requirement. But in the primary key, id is still at the end.

Sign up to request clarification or add additional context in comments.

4 Comments

When i try to add such key in InnoDB: alter table user drop primary key, add primary key (username(12), password(4), id); I'm getting an error: Error Code: 1075. Incorrect table definition; there can be only one auto column and it must be defined as a key
InnoDB requires the auto-increment column be the first column in the key.
Correction: "InnoDB requires the auto-increment column be the first column in SOME key."
@NoActualName - Do not use "prefixing" ((12), etc). It defeats the usefulness of the index. In particular, it won't look beyond the first such prefixed column. Please provide your CREATE TABLE so that we don't have to dance around the various edge cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.