2013-08-05 79 views
1

考虑一个表具有以下字段:结合覆盖指数具有唯一约束在MySQL

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

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

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

只有在where子句中使用具有值的查询时,您才能从值中获得索引的好处。

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

+0

我误解了覆盖索引的目的吗?我认为目的是通过消除查询记录的需要来加速数据检索,因为数据已经包含在索引中。 – alexpirine