MySQL在同一查询上的索引使用不一致

时间:2012-06-15 20:11:45

标签: mysql indexing

我有一张超过900万行的表格。我有一个SELECT查询,我使用索引。这是查询:

SELECT `username`,`id`
FROM `04c1Tg0M`
WHERE `id` > 9259466
AND `tried` = 0
LIMIT 1;

该查询执行速度非常快(0.00秒)。以下是该查询的解释:

+----+-------------+----------+-------+-----------------+---------+---------+------+-------+-------------+
| id | select_type | table    | type  | possible_keys   | key     | key_len | ref  | rows  | Extra       |
+----+-------------+----------+-------+-----------------+---------+---------+------+-------+-------------+
|  1 | SIMPLE      | 04c1Tg0M | range | PRIMARY,triedex | PRIMARY | 4       | NULL | 10822 | Using where |
+----+-------------+----------+-------+-----------------+---------+---------+------+-------+-------------+

现在这里是相同的查询,除了我要将ID更改为6259466:

SELECT `username`,`id`
FROM `04c1Tg0M`
WHERE `id` > 5986551
AND `tried` = 0
LIMIT 1;

该查询需要4.78秒才能完成。这就是问题。以下是该查询的解释:

+----+-------------+----------+------+-----------------+---------+---------+-------+---------+-------------+
| id | select_type | table    | type | possible_keys   | key     | key_len | ref   | rows    | Extra       |
+----+-------------+----------+------+-----------------+---------+---------+-------+---------+-------------+
|  1 | SIMPLE      | 04c1Tg0M | ref  | PRIMARY,triedex | triedex | 2       | const | 9275107 | Using where |
+----+-------------+----------+------+-----------------+---------+---------+-------+---------+-------------+

这里发生了什么,我该如何解决?这是我的索引:

+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table    | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| 04c1Tg0M |          0 | PRIMARY  |            1 | id          | A         |     9275093 |     NULL | NULL   |      | BTREE      |         |
| 04c1Tg0M |          1 | pdex     |            1 | username    | A         |     9275093 |     NULL | NULL   |      | BTREE      |         |
| 04c1Tg0M |          1 | pdex     |            2 | id          | A         |     9275093 |     NULL | NULL   |      | BTREE      |         |
| 04c1Tg0M |          1 | pdex     |            3 | tried       | A         |     9275093 |     NULL | NULL   | YES  | BTREE      |         |
| 04c1Tg0M |          1 | triedex  |            1 | tried       | A         |           0 |     NULL | NULL   | YES  | BTREE      |         |
| 04c1Tg0M |          1 | triedex  |            2 | id          | A         |     9275093 |     NULL | NULL   |      | BTREE      |         |
+----------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

这是我的表结构:

| 04c1Tg0M | CREATE TABLE `04c1Tg0M` (
`id` int(20) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`tried` tinyint(1) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `pdex` (`username`,`id`,`tried`),
KEY `triedex` (`tried`,`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9275108 DEFAULT CHARSET=utf8 |

1 个答案:

答案 0 :(得分:1)

第一个SQL返回10822行,而第二个返回9275107行!

在第二个查询中使用主键“id”索引并不是很有用,因为无论如何都必须进行全表扫描。

MySQL的基于成本的优化器认为,在第二个查询的情况下,最好在'试用'上使用索引。

如果你必须进行全表扫描,最好不要使用索引,因为索引会构成额外的磁盘读取。

您可以在查询中使用“use index”或“force index”来提示优化器是否使用索引。

还会定期分析您的表格以更新统计信息,以便基于成本的优化器正常运行。