Ketika melihat permintaan yang sangat mengganggu atas tabel MyISAM yang membutuhkan waktu lama untuk dieksekusi pada beberapa kesempatan, saya telah mencatat bahwa MySQL tampaknya mengekspos pola I / O yang agak aneh: ketika mengeksekusi permintaan tunggal dan harus melakukan signifikan jumlah I / O (misalnya untuk pemindaian tabel atau ketika cache kosong sebagai akibatnya echo 3 > /proc/sys/vm/drop_caches
sehingga indeks harus dimuat dari disk terlebih dahulu), ukuran antrian untuk perangkat blok yang mendasarinya mendekati nilai 1, dengan kinerja luar biasa dari hanya 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
Sementara 150 IOPS adalah disk tunggal dalam konfigurasi yang diberikan yang mampu menghasilkan I / O acak, hasilnya masih sangat mengejutkan saya karena saya berharap MySQL dapat menjalankan I / O asinkron untuk membaca dan mengambil sejumlah besar blok secara bersamaan alih-alih membaca dan mengevaluasinya satu per satu, secara efektif mengabaikan perolehan paralelisasi yang tersedia dalam konfigurasi RAID. Apa keputusan desain atau opsi konfigurasi yang bertanggung jawab untuk ini? Apakah ini masalah khusus platform?
Sementara saya telah menguji ini dengan tabel MyISAM besar-ish, saya melihat efek yang sama dengan tabel yang sama dikonversi ke InnoDB (meskipun tidak seburuk itu, permintaan sampel masih membutuhkan waktu 20-30 detik dengan sebagian besar waktu dihabiskan untuk membaca disk dengan panjang antrian 1) setelah saya me-restart daemon mysql dan oleh karena itu kolam buffer kosong. Saya juga telah memverifikasi bahwa masalah yang sama tetap pada 5,6 GA dan saat ini 5,7 tonggak sejarah 14 - selama saya menggunakan utas permintaan tunggal, MySQL tampaknya tidak dapat memparalelkan operasi I / O yang diperlukan untuk pemrosesan permintaan.
Sesuai permintaan beberapa detail tambahan pada skenario. Perilaku dapat diamati dengan banyak jenis kueri. Saya telah secara sewenang-wenang memilih satu untuk pengujian lebih lanjut yang berbunyi seperti ini:
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;
Saya tahu bahwa ia memiliki beberapa ruang untuk optimasi, tetapi saya memutuskan untuk berhenti karena beberapa alasan dan berkonsentrasi pada mencari penjelasan umum untuk pola I / O yang tidak terduga yang saya lihat.
Tabel yang digunakan memang memiliki banyak data di dalamnya:
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)
Sekarang ketika saya menjalankan kueri di atas tabel-tabel ini, saya mendapatkan waktu eksekusi lebih dari 1 menit sementara sistem tampaknya terus-menerus sibuk membaca data dari disk dengan satu utas.
Profil untuk eksekusi permintaan sampel (yang mengambil 1 menit 9,17 detik dalam contoh ini) terlihat seperti ini:
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)