Khi xem xét một truy vấn đặc biệt khó chịu trên các bảng MyISAM, phải mất một thời gian dài để thực thi trong một số trường hợp, tôi đã lưu ý rằng MySQL dường như để lộ một mẫu I / O khá lạ: khi thực hiện một truy vấn duy nhất và phải thực hiện một truy vấn quan trọng số lượng I / O (ví dụ để quét bảng hoặc khi bộ đệm trống do kết quả của echo 3 > /proc/sys/vm/drop_caches
các chỉ mục cần được tải ra khỏi đĩa trước), kích thước hàng đợi cho thiết bị khối bên dưới gần giá trị 1, với hiệu suất vượt trội của chỉ 4-5 MB / s:
root@mysql-test:~# iostat -xdm 5 /dev/sda
Linux 3.2.0-40-generic (mysql-test) 04/30/2014 _x86_64_ (4 CPU)
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.14 24.82 18.26 88.79 0.75 4.61 102.56 2.83 26.39 19.29 27.85 2.46 26.31
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 69.29 151.52 72.73 5.31 0.59 53.95 1.21 5.39 7.84 0.29 4.39 98.51
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 153.06 144.29 174.69 4.96 1.36 40.54 1.39 4.36 8.91 0.60 3.15 100.49
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 105.75 150.92 109.03 4.53 0.85 42.41 1.29 4.96 8.15 0.54 3.90 101.36
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 48.89 156.36 51.72 5.28 0.76 59.38 1.28 6.16 8.02 0.55 4.77 99.23
Mặc dù 150 IOPS chỉ đơn giản là những gì một đĩa đơn trong cấu hình đã cho có khả năng phân phối theo I / O ngẫu nhiên, kết quả vẫn thực sự làm tôi ngạc nhiên vì tôi mong đợi MySQL có thể chạy I / O không đồng bộ để đọc và tìm nạp số lượng lớn các khối đồng thời thay vì đọc và đánh giá từng khối một, bỏ qua hiệu quả song song hóa có sẵn trong các cấu hình RAID. Quyết định thiết kế hoặc tùy chọn cấu hình nào chịu trách nhiệm cho việc này? Đây có phải là một vấn đề cụ thể nền tảng?
Trong khi tôi đã thử nghiệm điều này với các bảng MyISAM lớn, tôi thấy các hiệu ứng tương tự với các bảng tương tự được chuyển đổi thành InnoDB (mặc dù không tệ như vậy, truy vấn mẫu vẫn mất 20-30 giây với phần lớn thời gian dành cho việc đọc đĩa với độ dài hàng đợi là 1) sau khi tôi khởi động lại daemon mysql và do đó các vùng đệm trống. Tôi cũng đã xác minh rằng vấn đề tương tự vẫn tồn tại trên 5.6 GA và mốc 5,7 hiện tại - miễn là tôi đang sử dụng một chuỗi truy vấn duy nhất, MySQL dường như không thể song song hóa các hoạt động I / O cần thiết cho xử lý truy vấn.
Theo yêu cầu một số chi tiết bổ sung về kịch bản. Hành vi có thể được quan sát với vô số loại truy vấn. Tôi đã tùy ý chọn một cái để kiểm tra thêm mà đọc phần nào như thế này:
SELECT herp.id, herp.firstname, herp.lastname, derp.label, herp.email,
(SELECT CONCAT(label, " (", zip_code, " ", city,")" ) FROM subsidiaries WHERE subsidiaries.id=herp.subsidiary_id ) AS subsidiary,
(SELECT COUNT(fk_herp) from herp_missing_data WHERE fk_herp=herp.id) AS missing_data
FROM herp LEFT JOIN derp ON derp.id=herp.fk_derp
WHERE (herp.fk_pools='123456') AND herp.city LIKE '%Some City%' AND herp.active='yes'
ORDER BY herp.id desc LIMIT 0,10;
Tôi biết rằng nó có một số chỗ để tối ưu hóa, nhưng tôi đã quyết định để nó ở đó vì một số lý do và tập trung vào việc tìm một lời giải thích chung cho mẫu I / O bất ngờ mà tôi đang thấy.
Các bảng được sử dụng có một loạt dữ liệu trong đó:
mysql> select table_name, engine, table_rows, data_length, index_length from information_schema.tables WHERE tables.TABLE_SCHEMA = 'mydb' and tables.table_name in ( 'herp', 'derp', 'missing_data', 'subsidiaries');
+-------------------------+--------+------------+-------------+--------------+
| table_name | engine | table_rows | data_length | index_length |
+-------------------------+--------+------------+-------------+--------------+
| derp | MyISAM | 14085 | 1118676 | 165888 |
| herp | MyISAM | 821747 | 828106512 | 568057856 |
| missing_data | MyISAM | 1220186 | 15862418 | 29238272 |
| subsidiaries | MyISAM | 1499 | 6490308 | 103424 |
+-------------------------+--------+------------+-------------+--------------+
4 rows in set (0.00 sec)
Bây giờ khi tôi đang chạy truy vấn ở trên các bảng này, tôi nhận được thời gian thực hiện hơn 1 phút trong khi hệ thống dường như liên tục bận đọc dữ liệu ra khỏi đĩa với một luồng.
Cấu hình để thực hiện truy vấn mẫu (mất 1 phút 9,17 giây trong ví dụ này) trông như thế này:
mysql> show profile for query 1;
+--------------------------------+-----------+
| Status | Duration |
+--------------------------------+-----------+
| starting | 0.000118 |
| Waiting for query cache lock | 0.000035 |
| init | 0.000033 |
| checking query cache for query | 0.000399 |
| checking permissions | 0.000077 |
| checking permissions | 0.000030 |
| checking permissions | 0.000031 |
| checking permissions | 0.000035 |
| Opening tables | 0.000158 |
| init | 0.000294 |
| System lock | 0.000056 |
| Waiting for query cache lock | 0.000032 |
| System lock | 0.000116 |
| optimizing | 0.000063 |
| statistics | 0.001964 |
| preparing | 0.000104 |
| Sorting result | 0.000033 |
| executing | 0.000030 |
| Sending data | 2.031349 |
| optimizing | 0.000054 |
| statistics | 0.000039 |
| preparing | 0.000024 |
| executing | 0.000013 |
| Sending data | 0.000044 |
| optimizing | 0.000017 |
| statistics | 0.000021 |
| preparing | 0.000019 |
| executing | 0.000013 |
| Sending data | 21.477528 |
| executing | 0.000070 |
| Sending data | 0.000075 |
| executing | 0.000027 |
| Sending data | 45.692623 |
| end | 0.000076 |
| query end | 0.000036 |
| closing tables | 0.000109 |
| freeing items | 0.000067 |
| Waiting for query cache lock | 0.000038 |
| freeing items | 0.000080 |
| Waiting for query cache lock | 0.000044 |
| freeing items | 0.000037 |
| storing result in query cache | 0.000033 |
| logging slow query | 0.000103 |
| cleaning up | 0.000073 |
+--------------------------------+-----------+
44 rows in set, 1 warning (0.00 sec)