は、私は次のMySQLのテーブル(簡体字)があります。MySQLでこのインデックスを削除するとクエリが100倍高速になるのはなぜですか?
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」カラムは、私がほとんどで無視する行をマークし、すべてではないが、私のクエリの。私はこのテーブルからチャンクを定期的に読み出すクエリをいくつか持っています。そのうちの1つは次のようになります。
SELECT id,title from track where (track.is_active=1 and track.id > 5580702) ORDER BY id ASC LIMIT 10;
このクエリは実行に1分かかります。
> 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 |
+----+-------------+-------+------+----------------+--------+---------+-------+---------+-------------+
ここで、is_activeインデックスを無視するようにMySQLに指示すると、クエリは即座に実行されます。今
> 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 |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
、本当に奇妙なのは、私が「is_active」インデックスを使用してMySQLを強制すると、クエリが再び瞬時に起こるということです!
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| 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を実行
- 無効になり、TABLEをANALYZEは
- 6620372行が 'is_active' Trueに設定した効果がなかったです。 874,714行に 'is_active'がFalseに設定されています。
- FORCE INDEX(is_active)を使用すると、クエリが高速化されます。
- MySQLバージョン5.1.54
ベンチマークの前にキャッシュをクリアしていますか? – dfb
また、テーブルの統計情報が最新でインデックスが再構築されていることを確認してください。 (しかしこれはMySQLで行われます;-) –
WHERE条件を逆にするとどうなりますか? 'どこで(track.id> 5580702とtrack.is_active = 1)' – EJP