Tôi đã gặp một số sự cố lạ khi cập nhật Máy chủ MySQL lên phiên bản 5.7 (theo Ubuntu 16.04 LTS).MySQL 5.7 Giảm nhiễu phi thường với thứ tự ASC/DESC trên bảng được phân đoạn
Preambula: Tôi có một số bảng có nhiều bản ghi (~ 250 triệu). Bảng này, trong ngắn hạn, có cấu trúc như vậy:
CREATE TABLE `device_data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`device` int(11) DEFAULT NULL,
`data` double NOT NULL DEFAULT '0',
`utc` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`utc`,`id`),
KEY `id` (`id`),
KEY `idx_devutc` (`device`,`utc`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (`utc`)
(PARTITION y_min VALUES LESS THAN (1200000000) ENGINE = MyISAM,
PARTITION y_121 VALUES LESS THAN (1210000000) ENGINE = MyISAM,
PARTITION y_122 VALUES LESS THAN (1220000000) ENGINE = MyISAM,
...
...
...
PARTITION y_167 VALUES LESS THAN (1670000000) ENGINE = MyISAM,
PARTITION y_168 VALUES LESS THAN (1680000000) ENGINE = MyISAM,
PARTITION y_169 VALUES LESS THAN (1690000000) ENGINE = MyISAM,
PARTITION y_max VALUES LESS THAN MAXVALUE ENGINE = MyISAM) */
Vì vậy, tại sao khóa chính không bình thường như vậy (UTC, ID)? Field ID là autoincrement và nó cùng có thể là một khóa chính. Vâng, chúng ta cần phân vùng bảng theo trường UTC và MySQL nói rằng để làm như vậy, trường UTC phải là khóa chính hoặc ít nhất là phần đầu tiên của khóa chính. Chúng tôi không thể sử dụng UTC cùng với khóa chính vì thiết bị có thể gửi dữ liệu nhiều lần trong một giây, vì vậy chúng tôi phải sử dụng khóa chính lạ như vậy: (UTC, ID). Điều này là OK.
Chúng tôi cũng có và lập chỉ mục trên bảng này theo (thiết bị, utc). Tại sao? Vì chúng tôi cần thực thi truy vấn để truy xuất dữ liệu theo một số thiết bị nhất định trong một khoảng thời gian nhất định, ví dụ:
SELECT `utc`, `data`
FROM `device_data`
WHERE `device` = :DeviceId AND `utc` >= :UtcFrom AND `utc` < :UtcTo
ORDER BY `utc`;
Rất nhanh vì chỉ mục (thiết bị, utc).
Ambula: Sau khi nâng cấp máy chủ MySQL lên phiên bản 5.7 (từ 5.0 hoặc 5.1, tôi không chắc chắn) một số truy vấn trở nên rất chậm (2-3 phút thay vì 100-200 millisesonds). Một số điều tra nhỏ đã tìm thấy một điều kiện: tốc độ truy vấn rơi xuống, khi thứ tự sắp xếp là hậu duệ.
Truy vấn này vẫn còn nhanh (100 milllseconds):
SELECT `utc`, `data`
FROM `device_data`
WHERE `device` = :DeviceId AND `utc` >= :UtcFrom AND `utc` < :UtcTo
ORDER BY `utc` ASC;
Nhưng truy vấn này là rất chậm (~ 180 giây):
SELECT `utc`, `data`
FROM `device_data`
WHERE `device` = :DeviceId AND `utc` >= :UtcFrom AND `utc` < :UtcTo
ORDER BY `utc` DESC;
Với các giá trị param cùng, tất nhiên. Theo phiên bản trước của MySQL Server, cả hai truy vấn đều nhanh (100-200 mili giây).
Sau hai ngày làm việc tích cực Tôi tìm thấy một số mẹo để tránh những vấn đề:
SELECT `utc`, `data`
FROM `device_data`
WHERE `device` = :DeviceId AND `utc` >= :UtcFrom AND `utc` < :UtcTo
ORDER BY -`utc` ASC;
(Attantion vào dấu trừ trước utc
trong ORDER BY)
Truy vấn này cũng nhanh chóng, hoàn thiện trong mili giây và trả lại hồ sơ theo thứ tự ngược lại, như chúng ta cần.
Nhưng câu hỏi là:
Câu hỏi: lý do của một hành vi kỳ lạ như MySQL là gì, và làm thế nào tôi có thể sửa chữa nó?
Bạn có ý tưởng nào không?
Cảm ơn.
Bạn có thể kiểm tra xem chỉ mục nào chậm và truy vấn nhanh sử dụng với giải thích? – Shadow
Không có bất ngờ, cả hai đều sử dụng idx_devutc. Hơn nữa, các truy vấn tương tự với trình điều chỉnh 'FORCE INDEX (idx_devutc)' hiển thị cùng một kết quả. – tumick
Không có tệp nào trong phần bổ sung? – Shadow