我有以下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