✦ Selamat Idul Fitri 1447 H πŸŒ™ Taqabbalallahu minna wa minkum. Mohon maaf lahir dan batin. ✦
Oprek Blog

Optimasi Query MySQL yang Bikin Halaman Blog Ini 3x Lebih Cepat

Β· 0 komentar Β· Β± 4 menit baca Β· πŸ‘ 80 dilihat

Ceritanya biasa aja sebenernya. Blog ini jalan normal, tidak ada yang komplain. Tapi waktu saya iseng ukur loading time pakai Google PageSpeed Insights, hasilnya cukup bikin saya duduk lebih tegak.

Skornya 54. Untuk blog sederhana yang isinya cuma teks dan gambar β€” itu jelek.

Saya mulai investigasi. Dan ternyata biang keroknya bukan gambar yang tidak dioptimasi atau JavaScript yang berat. Masalahnya ada di query database yang saya tulis dengan santai beberapa tahun lalu dan tidak pernah saya sentuh sejak.

Query yang Kelihatan Tidak Masalah Tapi Ternyata Masalah

Blog ini waktu saya buat punya mungkin 10 artikel. Query apapun jalan cepat karena datanya kecil. Tapi sekarang sudah lebih dari tiga puluh artikel β€” masih kecil memang, tapi cukup untuk mulai kelihatan bedanya kalau query-nya tidak efisien.

Query awal untuk halaman beranda saya kira-kira seperti ini (disederhanakan):

SELECT * FROM posts 
ORDER BY created_at DESC

Kelihatannya tidak masalah. Tapi SELECT * mengambil semua kolom β€” termasuk kolom content yang isinya konten artikel lengkap. Untuk halaman beranda yang hanya menampilkan judul, slug, dan tanggal, mengambil seluruh konten itu pemborosan total.

Saya ganti jadi:

SELECT id, title, slug, category_id, created_at, views 
FROM posts
ORDER BY created_at DESC
LIMIT 10

Perubahan kecil, tapi transfer data dari database ke PHP turun drastis. Konten artikel bisa ribuan karakter β€” mengalikan itu dengan jumlah artikel dan kirim semuanya cuma untuk tampilkan thumbnail adalah pemborosan yang jelas.

Index: Yang Paling Sering Dilupakan

Query kedua yang bermasalah ada di halaman kategori:

SELECT id, title, slug, created_at 
FROM posts
WHERE category_id = 2
ORDER BY created_at DESC

Saya jalankan EXPLAIN untuk lihat apa yang MySQL lakukan:

EXPLAIN SELECT id, title, slug, created_at 
FROM posts
WHERE category_id = 2
ORDER BY created_at DESC;

Hasilnya: type "ALL" β€” artinya MySQL melakukan full table scan, baca setiap baris untuk mencari yang cocok dengan category_id = 2. Dengan 30 artikel ini tidak kelihatan lambat, tapi kalau isinya ribuan artikel β€” bencana.

Solusinya: tambahkan index pada kolom category_id.

ALTER TABLE posts ADD INDEX idx_category_id (category_id);
ALTER TABLE posts ADD INDEX idx_created_at (created_at);

Setelah itu EXPLAIN menunjukkan type "ref" β€” MySQL sekarang menggunakan index untuk mencari, bukan membaca semua baris. Perbedaannya kecil untuk data kecil, tapi prinsipalnya benar.

Query N+1: Bug yang Paling Sering Tidak Disadari

Ini yang paling lucu sekaligus memalukan waktu saya temukan. Di halaman beranda, untuk setiap artikel saya tampilkan nama kategorinya. Kode PHP saya waktu itu kira-kira seperti ini:

// Ambil semua artikel
$posts = query("SELECT * FROM posts ORDER BY created_at DESC LIMIT 10");
foreach ($posts as $post) {
// Ambil nama kategori untuk SETIAP artikel
$category = query("SELECT name FROM categories WHERE id = " . $post['category_id']);
echo $category['name'];
}

Kelihatannya tidak masalah. Tapi ini adalah N+1 query problem yang klasik: 1 query untuk dapat 10 artikel, lalu 10 query tambahan untuk dapat nama kategori masing-masing. Total 11 query untuk satu halaman.

Solusinya: JOIN sekali, selesai.

SELECT p.id, p.title, p.slug, p.created_at, c.name as category_name
FROM posts p
LEFT JOIN categories c ON p.category_id = c.id
ORDER BY p.created_at DESC
LIMIT 10

Satu query. Semua data yang dibutuhkan sudah ada. Tidak ada loop query yang mubazir.

Hasilnya

Setelah tiga perubahan itu β€” ganti SELECT *, tambah index, dan fix N+1 query β€” saya ukur lagi. Skor PageSpeed naik dari 54 ke 87. Bukan sempurna, tapi jauh lebih baik.

Yang paling saya ingat dari proses ini: semua masalahnya ada di kode yang saya tulis sendiri bertahun-tahun lalu, dan saya tidak pernah terpikir untuk mengauditnya. Performa itu bukan sesuatu yang bisa dioptimasi sekali lalu dilupakan β€” ia perlu dicek ulang seiring data yang bertambah.

Kalau Anda punya blog atau web app dengan PHP dan MySQL, coba jalankan EXPLAIN pada query-query utama Anda. Mungkin ada kejutan yang sama seperti yang saya temukan.

Ada pengalaman serupa atau teknik optimasi lain yang mau dibagikan? Kolom komentar terbuka β€” saya selalu belajar dari pengalaman orang lain.


Komentar

Belum ada komentar. Jadilah yang pertama menulis.

Tulis Komentar

↑