我有以下MySQL表(简体):为什么在MySQL中删除这个索引加快了我的查询100x?
CREATE TABLE `track` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(256) NOT NULL,
`is_active` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
KEY `is_active` (`is_active`, `id`)
) ENGINE=MyISAM AUTO_INCREMENT=7495088 DEFAULT CHARSET=utf8
的“IS_ACTIVE”列标志着我想在最忽略行,但不是全部,我的查询。我有一些查询会定期从这张表中读取块。其中一个看起来像这样:
SELECT id,title from track where (track.is_active=1 and track.id > 5580702) ORDER BY id ASC LIMIT 10;
该查询需要一分钟才能执行。下面是执行计划:
> EXPLAIN SELECT id,title from track where (track.is_active=1 and track.id > 5580702) ORDER BY id ASC LIMIT 10;
+----+-------------+-------+------+----------------+--------+---------+-------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+----------------+--------+---------+-------+---------+-------------+
| 1 | SIMPLE | t | ref | PRIMARY,is_active | is_active | 1 | const | 3747543 | Using where |
+----+-------------+-------+------+----------------+--------+---------+-------+---------+-------------+
现在,如果我告诉MySQL忽略“IS_ACTIVE人指数,查询发生瞬间。
> EXPLAIN SELECT id,title from track IGNORE INDEX(is_active) WHERE (track.is_active=1 AND track.id > 5580702) ORDER BY id ASC LIMIT 10;
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| 1 | SIMPLE | t | range | PRIMARY | PRIMARY | 4 | NULL | 1597518 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
现在,什么是真正奇怪的是,如果我强迫MySQL使用了“IS_ACTIVE人指数,查询再次发生瞬间!
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| 1 | SIMPLE | t | range | is_active |is_active| 5 | NULL | 1866730 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
我只是不明白这种行为。在'is_active'索引中,行应按is_active排序,后跟id。我在查询中同时使用了'is_active'和'id'列,所以它似乎应该只需要在树上做几跳就可以找到ID,然后使用这些ID从表中检索标题。
发生了什么事?
编辑:更多信息关于我在做什么:
- 查询缓存被禁用
- 运行OPTIMIZE TABLE和ANALYZE TABLE没有效果
- 6620372行已 'IS_ACTIVE' 设置为True。 874,714行将'is_active'设置为False。
- 使用FORCE INDEX(is_active)再次加快查询速度。
- MySQL版本54年1月5日
您在基准测试之前清除缓存,对吧? – dfb
同时确保表格统计数据是当前的,并且索引被重建。 (然而,这是在MySQL中完成的;-) – 2011-09-29 02:09:47
如果您反转WHERE条件会发生什么? 'where(track.id> 5580702 and track.is_active = 1)' – EJP