让我们从一个简单的例子开始:
CREATE TABLE `test` (
`id` INT UNSIGNED NOT NULL,
`value` CHAR(12) NOT NULL,
INDEX (`id`),
INDEX (`value`)
) ENGINE = InnoDB;
所以 2 列,都被索引。我认为这意味着 MySQL 将不再需要读取实际的表,因为所有数据都存储在索引中。
mysql> EXPLAIN SELECT id FROM test WHERE id = 1;
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
| 1 | SIMPLE | test | ref | id | id | 4 | const | 1 | Using index |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------------+
“使用索引”,非常好。据我了解,这意味着它是从索引中读取数据,而不是从实际表中读取数据。但我真正想要的是“价值”列。
mysql> EXPLAIN SELECT value FROM test WHERE id = 1;
+----+-------------+-------+------+---------------+------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------+
| 1 | SIMPLE | test | ref | id | id | 4 | const | 1 | |
+----+-------------+-------+------+---------------+------+---------+-------+------+-------+
嗯,这次没有“使用索引”。
我认为如果我添加一个涵盖两列的索引可能会有所帮助。
ALTER TABLE `test` ADD INDEX `id_value` (`id`,`value`);
现在让我们再次运行之前的选择语句并告诉它使用新索引。
mysql> EXPLAIN SELECT id, value FROM test USE INDEX (id_value) WHERE id = 1;
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
| 1 | SIMPLE | test | ref | id_value | id_value | 4 | const | 1 | Using index |
+----+-------------+-------+------+---------------+----------+---------+-------+------+-------------+
赞美主,它是从索引中读取的。
但实际上我并不真的需要组合索引来做其他事情。是否可以让 MySQL 从 2 个单独的索引中读取?
任何见解将不胜感激。
编辑:好的,还有另一个例子。这个是原始表定义(所以每列都有一个索引)。
mysql> EXPLAIN SELECT t1.value
-> FROM test AS t1
-> INNER JOIN test AS t2
-> ON t1.id <> t2.id AND t1.value = t2.value
-> WHERE t1.id = 1;
+----+-------------+-------+------+---------------+-------+---------+----------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+-------+---------+----------+------+-------------+
| 1 | SIMPLE | t1 | ref | id,value | id | 4 | const | 1 | |
| 1 | SIMPLE | t2 | ref | value | value | 12 | t1.value | 1 | Using where |
+----+-------------+-------+------+---------------+-------+---------+----------+------+-------------+
这肯定必须从两个索引中读取(因为在连接条件中使用了两个字段)但它仍然从实际记录中读取数据,对吗?为什么它不只使用从索引中读取的数据?还是它实际上使用了这些数据而不说“使用索引”?
再次感谢