Tôi có bảng sau MySQL (giản thể):Tại sao loại bỏ chỉ mục này trong MySQL tăng tốc độ truy vấn của tôi 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
Cột 'is_active' đánh dấu hàng mà tôi muốn bỏ qua ở hầu hết, nhưng không phải tất cả, các truy vấn của tôi. Tôi có một số truy vấn đọc từng phần trong bảng này theo định kỳ. Một trong số họ trông giống như sau:
SELECT id,title from track where (track.is_active=1 and track.id > 5580702) ORDER BY id ASC LIMIT 10;
Truy vấn này mất hơn một phút để thực thi. Đây là kế hoạch thực hiện:
> 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 |
+----+-------------+-------+------+----------------+--------+---------+-------+---------+-------------+
Bây giờ, nếu tôi yêu cầu MySQL bỏ qua chỉ mục 'is_active', truy vấn diễn ra ngay lập tức.
> 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 |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
Bây giờ, điều thực sự lạ là nếu tôi sử dụng MySQL để sử dụng chỉ mục 'is_active', truy vấn lại một lần nữa xảy ra ngay lập tức!
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
| 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 |
+----+-------------+-------+-------+---------------+---------+---------+------+---------+-------------+
Tôi không hiểu hành vi này. Trong chỉ mục 'is_active', các hàng phải được sắp xếp theo is_active, theo sau là id. Tôi sử dụng cả hai cột 'is_active' và 'id' trong truy vấn của mình, vì vậy có vẻ như chỉ cần thực hiện một vài bước nhảy quanh cây để tìm ID, sau đó sử dụng các ID đó để truy xuất các tiêu đề từ bảng.
gì đang xảy ra?
EDIT: Thông tin thêm về những gì tôi đang làm:
- Query bộ nhớ cache bị vô hiệu hóa
- Chạy TỐI ƯU HÓA TABLE và phân tích TABLE không ảnh hưởng
- 6.620.372 hàng đã 'is_active' thiết lập là True. 874.714 hàng có 'is_active' được đặt thành False.
- Sử dụng FORCE INDEX (is_active) một lần nữa tăng tốc truy vấn.
- Phiên bản MySQL 5.1.54
Bạn đang xóa bộ nhớ cache trước khi đo điểm chuẩn, phải không? – dfb
Đồng thời đảm bảo thống kê bảng là hiện tại và các chỉ mục được xây dựng lại. (Tuy nhiên điều này được thực hiện trong MySQL ;-) –
Điều gì sẽ xảy ra nếu bạn đảo ngược điều kiện WHERE? 'where (track.id> 5580702 và track.is_active = 1)' – EJP