Beban kerja database MySQL ditentukan oleh jumlah kueri yang diproses. Ada beberapa situasi di mana kelambatan MySQL dapat berasal. Kemungkinan pertama adalah jika ada kueri yang tidak menggunakan pengindeksan yang tepat. Ketika kueri tidak dapat menggunakan indeks, server MySQL harus menggunakan lebih banyak sumber daya dan waktu untuk memproses kueri itu. Dengan memantau kueri, Anda memiliki kemampuan untuk menentukan kode SQL yang merupakan akar penyebab pelambatan dan memperbaikinya sebelum kinerja keseluruhan menurun.
Dalam posting blog ini, kita akan menyoroti fitur Query Outlier yang tersedia di ClusterControl dan melihat bagaimana fitur tersebut dapat membantu kita meningkatkan kinerja database. Secara umum, ClusterControl melakukan pengambilan sampel kueri MySQL dengan dua cara:
- Ambil kueri dari Skema Kinerja (disarankan ).
- Parsing konten MySQL Slow Query.
Jika Skema Kinerja dinonaktifkan, ClusterControl kemudian akan default ke log Kueri Lambat. Untuk mempelajari lebih lanjut tentang bagaimana ClusterControl melakukan ini, lihat posting blog ini, Cara menggunakan Monitor Kueri ClusterControl untuk Server MySQL, MariaDB, dan Percona.
Apa itu Query Outliers?
Pencilan adalah kueri yang membutuhkan waktu lebih lama daripada waktu kueri normal jenis itu. Jangan menganggap ini sebagai kueri yang "ditulis dengan buruk". Ini harus diperlakukan sebagai kueri umum suboptimal potensial yang dapat ditingkatkan. Setelah sejumlah sampel dan ketika ClusterControl memiliki statistik yang cukup, ia dapat menentukan apakah latensi lebih tinggi dari biasanya (2 sigma + rata-rata_query_time) maka itu adalah outlier dan akan ditambahkan ke dalam Query Outlier.
Fitur ini bergantung pada fitur Top Query. Jika Pemantauan Kueri diaktifkan dan Kueri Teratas ditangkap dan diisi, Pencilan Kueri akan meringkasnya dan menyediakan filter berdasarkan stempel waktu. Untuk melihat daftar kueri yang memerlukan perhatian, buka ClusterControl -> Query Monitor -> Query Outliers dan akan melihat beberapa kueri yang terdaftar (jika ada):
Seperti yang Anda lihat dari tangkapan layar di atas, outlier pada dasarnya adalah kueri yang memakan waktu setidaknya 2 kali lebih lama dari waktu kueri rata-rata. Pertama entri pertama, waktu rata-rata adalah 34,41 ms sedangkan waktu kueri outlier adalah 140 ms (lebih dari 2 kali lebih tinggi dari waktu rata-rata). Demikian pula, untuk entri berikutnya, kolom Waktu Kueri dan Waktu Kueri Rata-Rata adalah dua hal penting untuk membenarkan keunggulan kueri outlier tertentu.
Relatif mudah untuk menemukan pola outlier kueri tertentu dengan melihat periode waktu yang lebih besar, seperti seminggu yang lalu, seperti yang disorot dalam tangkapan layar berikut:
Dengan mengklik setiap baris, Anda dapat melihat kueri lengkap yang benar-benar membantu untuk menunjukkan dan memahami masalah, seperti yang ditunjukkan pada bagian berikutnya.
Memperbaiki Query Outlier
Untuk memperbaiki outlier, kita perlu memahami sifat kueri, mesin penyimpanan tabel, versi database, tipe pengelompokan, dan seberapa besar pengaruh kueri tersebut. Dalam beberapa kasus, kueri outlier tidak benar-benar menurunkan kinerja database secara keseluruhan. Seperti dalam contoh ini, kita telah melihat bahwa kueri telah menonjol sepanjang minggu dan itu adalah satu-satunya jenis kueri yang ditangkap, jadi mungkin ada baiknya untuk memperbaiki atau meningkatkan kueri ini jika memungkinkan.
Seperti dalam kasus kami, kueri outlier adalah:
SELECT i2l.country_code AS country_code, i2l.country_name AS country_name
FROM ip2location i2l
WHERE (i2l.ip_to >= INET_ATON('104.144.171.139')
AND i2l.ip_from <= INET_ATON('104.144.171.139'))
LIMIT 1
OFFSET 0;
Dan hasil kuerinya adalah:
+--------------+---------------+
| country_code | country_name |
+--------------+---------------+
| US | United States |
+--------------+---------------+
Menggunakan EXPLAIN
Kueri adalah kueri pemilihan rentang baca-saja untuk menentukan informasi lokasi geografis pengguna (kode negara dan nama negara) untuk alamat IP pada tabel ip2location. Menggunakan pernyataan EXPLAIN dapat membantu kami memahami rencana eksekusi kueri:
mysql> EXPLAIN SELECT i2l.country_code AS country_code, i2l.country_name AS country_name
FROM ip2location i2l
WHERE (i2l.ip_to>=INET_ATON('104.144.171.139')
AND i2l.ip_from<=INET_ATON('104.144.171.139'))
LIMIT 1 OFFSET 0;
+----+-------------+-------+------------+-------+--------------------------------------+-------------+---------+------+-------+----------+------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+--------------------------------------+-------------+---------+------+-------+----------+------------------------------------+
| 1 | SIMPLE | i2l | NULL | range | idx_ip_from,idx_ip_to,idx_ip_from_to | idx_ip_from | 5 | NULL | 66043 | 50.00 | Using index condition; Using where |
+----+-------------+-------+------------+-------+--------------------------------------+-------------+---------+------+-------+----------+------------------------------------+
Kueri dijalankan dengan pemindaian rentang pada tabel menggunakan indeks idx_ip_from dengan 50% baris potensial (difilter).
Mesin Penyimpanan yang Tepat
Melihat struktur tabel ip2location:
mysql> SHOW CREATE TABLE ip2location\G
*************************** 1. row ***************************
Table: ip2location
Create Table: CREATE TABLE `ip2location` (
`ip_from` int(10) unsigned DEFAULT NULL,
`ip_to` int(10) unsigned DEFAULT NULL,
`country_code` char(2) COLLATE utf8_bin DEFAULT NULL,
`country_name` varchar(64) COLLATE utf8_bin DEFAULT NULL,
KEY `idx_ip_from` (`ip_from`),
KEY `idx_ip_to` (`ip_to`),
KEY `idx_ip_from_to` (`ip_from`,`ip_to`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
Tabel ini didasarkan pada database IP2location dan jarang diperbarui/ditulis, biasanya hanya pada hari pertama bulan kalender (disarankan oleh vendor). Jadi salah satu opsi adalah mengonversi tabel ke mesin penyimpanan MyISAM (MySQL) atau Aria (MariaDB) dengan format baris tetap untuk mendapatkan kinerja read-only yang lebih baik. Perhatikan bahwa ini hanya berlaku jika Anda menjalankan MySQL atau MariaDB mandiri atau replikasi. Pada Galera Cluster dan Group Replication, harap tetap menggunakan mesin penyimpanan InnoDB (kecuali Anda tahu apa yang Anda lakukan).
Bagaimanapun, untuk mengonversi tabel dari InnoDB ke MyISAM dengan format baris tetap, cukup jalankan perintah berikut:
ALTER TABLE ip2location ENGINE=MyISAM ROW_FORMAT=FIXED;
Dalam pengukuran kami, dengan 1000 tes pencarian alamat IP acak, kinerja kueri meningkat sekitar 20% dengan MyISAM dan format baris tetap:
- Waktu rata-rata (InnoDB):21,467823 md
- Waktu rata-rata (MyISAM Fixed):17.175942 md
- Peningkatan:19.992157565301 %
Anda dapat mengharapkan hasil ini segera setelah tabel diubah. Tidak diperlukan modifikasi pada tingkat yang lebih tinggi (aplikasi/penyeimbang beban).
Menyetel Kueri
Cara lain adalah dengan memeriksa rencana kueri dan menggunakan pendekatan yang lebih efisien untuk rencana eksekusi kueri yang lebih baik. Query yang sama juga dapat ditulis menggunakan subquery seperti di bawah ini:
SELECT `country_code`, `country_name` FROM
(SELECT `country_code`, `country_name`, `ip_from`
FROM `ip2location`
WHERE ip_to >= INET_ATON('104.144.171.139')
LIMIT 1)
AS temptable
WHERE ip_from <= INET_ATON('104.144.171.139');
Kueri yang disetel memiliki rencana eksekusi kueri berikut:
mysql> EXPLAIN SELECT `country_code`,`country_name` FROM
(SELECT `country_code`, `country_name`, `ip_from`
FROM `ip2location`
WHERE ip_to >= INET_ATON('104.144.171.139')
LIMIT 1)
AS temptable
WHERE ip_from <= INET_ATON('104.144.171.139');
+----+-------------+--------------+------------+--------+---------------+-----------+---------+------+-------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------+------------+--------+---------------+-----------+---------+------+-------+----------+-----------------------+
| 1 | PRIMARY | <derived2> | NULL | system | NULL | NULL | NULL | NULL | 1 | 100.00 | NULL |
| 2 | DERIVED | ip2location | NULL | range | idx_ip_to | idx_ip_to | 5 | NULL | 66380 | 100.00 | Using index condition |
+----+-------------+--------------+------------+--------+---------------+-----------+---------+------+-------+----------+-----------------------+
Dengan menggunakan subquery, kita dapat mengoptimalkan kueri dengan menggunakan tabel turunan yang berfokus pada satu indeks. Kueri harus mengembalikan hanya 1 catatan di mana nilai ip_to lebih besar dari atau sama dengan nilai alamat IP. Ini memungkinkan baris potensial (difilter) mencapai 100% yang paling efisien. Kemudian, periksa apakah ip_from kurang dari atau sama dengan nilai alamat IP. Jika ya, maka kita harus menemukan catatannya. Jika tidak, alamat IP tidak ada di tabel ip2location.
Dalam pengukuran kami, kinerja kueri meningkat sekitar 99% menggunakan subkueri:
- Waktu rata-rata (InnoDB + pemindaian rentang):22.87112 md
- Waktu rata-rata (InnoDB + subkueri):0,14744 md
- Peningkatan:99.355344207017 %
Dengan optimasi di atas, kita dapat melihat waktu eksekusi kueri sub-milidetik dari jenis kueri ini, yang merupakan peningkatan besar mengingat waktu rata-rata sebelumnya adalah 22 ms. Namun, kami perlu melakukan beberapa modifikasi pada tingkat yang lebih tinggi (aplikasi/penyeimbang beban) untuk mendapatkan manfaat dari kueri yang disetel ini.
Menambal atau Menulis Ulang Kueri
Patch aplikasi Anda untuk menggunakan kueri yang disetel atau menulis ulang kueri outlier sebelum mencapai server database. Kita dapat mencapai ini dengan menggunakan penyeimbang beban MySQL seperti ProxySQL (aturan kueri) atau MariaDB MaxScale (filter penulisan ulang pernyataan), atau menggunakan plugin MySQL Query Rewriter. Dalam contoh berikut, kami menggunakan ProxySQL di depan cluster database kami dan kami dapat dengan mudah membuat aturan untuk menulis ulang kueri yang lebih lambat ke yang lebih cepat, misalnya:
Simpan aturan kueri dan pantau halaman Query Outliers di ClusterControl. Perbaikan ini jelas akan menghapus kueri outlier dari daftar setelah aturan kueri diaktifkan.
Kesimpulan
Pencilan kueri adalah alat pemantauan kueri proaktif yang dapat membantu kami memahami dan memperbaiki masalah kinerja sebelum menjadi tidak terkendali. Saat aplikasi Anda tumbuh dan menjadi lebih menuntut, alat ini dapat membantu Anda mempertahankan kinerja database yang layak di sepanjang jalan.