将覆盖索引与MySQL中的唯一约束相结合

时间:2013-08-05 14:34:18

标签: mysql unique-index covering-index

考虑一个包含以下字段的表:

mysql> DESCRIBE my_table;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| pk    | int(11)      | NO   | PRI | NULL    |       |
| name  | varchar(20)  | NO   | UNI |         |       |
| value | varchar(255) | NO   |     |         |       |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.01 sec)

请注意,字段名称具有唯一约束。

假设我想优化以下查询:

SELECT name, value
FROM my_table
WHERE name = 'my_name'

name字段已有索引(由于唯一约束),但为字段value设置覆盖索引会更好同样。

只有一个唯一约束索引,运行EXPLAIN命令时不会出现任何意外:

mysql> EXPLAIN
    -> SELECT name, value
    -> FROM my_table
    -> WHERE name = "my_name";
+----+-------------+----------+-------+---------------+------+---------+-------+------+-------+
| id | select_type | table    | type  | possible_keys | key  | key_len | ref   | rows | Extra |
+----+-------------+----------+-------+---------------+------+---------+-------+------+-------+
|  1 | SIMPLE      | my_table | const | name          | name | 62      | const |    1 |       |
+----+-------------+----------+-------+---------------+------+---------+-------+------+-------+

现在,如果我尝试添加覆盖索引,

ALTER TABLE my_table ADD INDEX idx_name_value (name, value);

它显示为查询的候选者,但未被选中!

mysql> EXPLAIN
    -> SELECT name, value
    -> FROM my_table
    -> WHERE name = "my_name";
+----+-------------+----------+-------+---------------------+------+---------+-------+------+-------+
| id | select_type | table    | type  | possible_keys       | key  | key_len | ref   | rows | Extra |
+----+-------------+----------+-------+---------------------+------+---------+-------+------+-------+
|  1 | SIMPLE      | my_table | const | name,idx_name_value | name | 62      | const |    1 |       |
+----+-------------+----------+-------+---------------------+------+---------+-------+------+-------+

请注意,如果我删除了唯一约束,

ALTER TABLE my_table DROP INDEX name;

覆盖指数按预期工作:

mysql> EXPLAIN
    -> SELECT name, value
    -> FROM my_table
    -> WHERE name = "my_name";
+----+-------------+----------+------+----------------+----------------+---------+-------+------+--------------------------+
| id | select_type | table    | type | possible_keys  | key            | key_len | ref   | rows | Extra                    |
+----+-------------+----------+------+----------------+----------------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | my_table | ref  | idx_name_value | idx_name_value | 62      | const |    1 | Using where; Using index |
+----+-------------+----------+------+----------------+----------------+---------+-------+------+--------------------------+

那么如何使用覆盖索引并仍然具有唯一约束?

1 个答案:

答案 0 :(得分:0)

  

名称字段已经有一个索引(由于唯一约束),但是为字段值设置覆盖索引会更好。

没有。使用唯一约束,您可以获得名称“免费”的索引。而且因为您只使用名称进行搜索,所以不需要覆盖(组合)索引和值。

当您在where子句中使用带值的查询时,您只能获得值索引的好处。

当您从不搜索值时,组合索引(名称,值)甚至会产生开销(因此从不使用索引)。在插入/更新操作中,必须更新索引,这可能会降低性能。