Tôi đang làm việc trên một lược đồ cho một hệ thống phân tích theo dõi thời gian sử dụng và cần phải xem tổng thời gian sử dụng trong một phạm vi ngày nhất định.
Để đưa ra một ví dụ đơn giản, loại truy vấn này sẽ được chạy thường xuyên:
select sum(diff_ms) from writetest_table where time_on > ("2015-07-13 15:11:56");
Truy vấn này thường mất khoảng 7 giây trên một bảng được đông dân cư. Nó có ~ 35 triệu hàng, MyISAM trên MySQL chạy trên Amazon RDS (db.m3.xlarge).
Việc loại bỏ mệnh đề WHERE làm cho truy vấn chỉ mất 4 giây và thêm mệnh đề thứ hai (time_off> XXX) thêm 1,5 giây nữa, đưa thời gian truy vấn lên 8,5 giây.
Vì tôi biết các loại truy vấn này sẽ được thực hiện phổ biến, tôi muốn tối ưu hóa mọi thứ để chúng nhanh hơn, lý tưởng là dưới 5 giây.
Tôi đã bắt đầu bằng cách thêm một chỉ mục vào time_on và mặc dù điều đó đã tăng tốc truy vấn WHERE "=", nhưng nó không có tác dụng đối với truy vấn ">". Có cách nào để tạo một chỉ mục giúp tăng tốc các truy vấn WHERE ">" hoặc "<" không?
Hoặc nếu có bất kỳ đề xuất nào khác về hiệu suất của loại truy vấn này, vui lòng cho tôi biết.
Lưu ý: Tôi đang sử dụng trường "diff_ms" làm bước không chuẩn hóa (bằng với time_off - time_on) giúp cải thiện hiệu suất tổng hợp khoảng 30% -40%.
Tôi đang tạo chỉ mục với lệnh này:
ALTER TABLE writetest_table ADD INDEX time_on (time_on) USING BTREE;
Chạy "giải thích" trên truy vấn ban đầu (với "time_on>") cho biết time_on là "could_key" và select_type là "SIMPLE". Cột "phụ" cho biết "Sử dụng ở đâu" và "loại" là "TẤT CẢ". Sau khi chỉ mục được thêm vào, bảng cho biết "time_on" là loại khóa "MUL", có vẻ đúng vì cùng một lúc có thể xuất hiện hai lần.
Đây là lược đồ bảng:
CREATE TABLE `writetest_table` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`sessionID` int(11) DEFAULT NULL,
`time_on` timestamp NULL DEFAULT NULL,
`time_off` timestamp NULL DEFAULT NULL,
`diff_ms` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `time_on` (`time_on`)
) ENGINE=MyISAM AUTO_INCREMENT=50410902 DEFAULT CHARSET=latin1;
CẬP NHẬT: Tôi đã tạo chỉ mục sau dựa trên phản hồi của ypercube, nhưng điều này làm tăng thời gian truy vấn cho truy vấn đầu tiên lên khoảng 17 giây!
ALTER TABLE writetest_table ADD INDEX time_on__diff_ms__ix (time_on, diff_ms) ;
CẬP NHẬT 2: đầu ra GIẢI THÍCH
mysql> explain select sum(diff_ms) from writetest_table where time_on > '2015-07-13 15:11:56';
+----+-------------+---------------------+-------+----------------------+----------------------+---------+------+----------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+-------+----------------------+----------------------+---------+------+----------+--------------------------+
| 1 | SIMPLE | writetest_table_old | index | time_on__diff_ms__ix | time_on__diff_ms__ix | 10 | NULL | 35831102 | Using where; Using index |
+----+-------------+---------------------+-------+----------------------+----------------------+---------+------+----------+--------------------------+
1 row in set (0.00 sec)
Cập nhật 3: kết quả của truy vấn được yêu cầu
mysql> SELECT time_on FROM writetest_table ORDER BY time_on LIMIT 1;
+---------------------+
| time_on |
+---------------------+
| 2015-07-13 15:11:56 |
+---------------------+
1 row in set (0.01 sec)
SELECT COUNT(*), COUNT(diff_ms) FROM writetest_table;
writetest_table_old
" trong khi truy vấn có from writetest_table
. Đó có phải là một lỗi đánh máy hoặc bạn chạy truy vấn trong bảng khác nhau?
time_on
vàdiff_ms
) không? Điều gì xảy ra nếu bạn thêm vào truy vấnWHERE ... AND diff_ms IS NOT NULL
?