考虑一个包含以下字段的表:
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 |
+----+-------------+----------+------+----------------+----------------+---------+-------+------+--------------------------+
那么如何使用覆盖索引并仍然具有唯一约束?
答案 0 :(得分:0)
名称字段已经有一个索引(由于唯一约束),但是为字段值设置覆盖索引会更好。
没有。使用唯一约束,您可以获得名称“免费”的索引。而且因为您只使用名称进行搜索,所以不需要覆盖(组合)索引和值。
当您在where子句中使用带值的查询时,您只能获得值索引的好处。
当您从不搜索值时,组合索引(名称,值)甚至会产生开销(因此从不使用索引)。在插入/更新操作中,必须更新索引,这可能会降低性能。