Aplikasi yang cepat saat datanya seribu baris sering menjadi lambat ketika datanya sejuta baris. Penyebab paling umum bukan server yang lemah, tetapi query yang tidak efisien. Artikel ini mengajarkan cara mengukur dulu, baru memperbaiki, dengan teknik yang berlaku di MySQL secara umum.
Prinsip utama: jangan menebak, ukur. Optimasi tanpa pengukuran sering membuang waktu pada bagian yang tidak bermasalah.
Langkah 1: Temukan query yang lambat
Slow query log merekam query yang melebihi batas waktu tertentu:
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- catat query yang > 1 detik
Lihat juga SHOW FULL PROCESSLIST; untuk melihat query yang sedang berjalan, dan gunakan alat seperti pt-query-digest untuk meringkas log. Prioritaskan query yang paling sering dipanggil × paling lama, bukan sekadar yang paling lambat satu kali.
Langkah 2: Baca hasil EXPLAIN
Tambahkan EXPLAIN di depan query untuk melihat rencana eksekusi:
EXPLAIN SELECT * FROM pesanan WHERE pelanggan_id = 42 ORDER BY dibuat_pada DESC;
Kolom yang perlu kamu perhatikan:
| Kolom | Arti | Yang dicari |
|---|---|---|
type | Cara tabel dibaca | const, eq_ref, ref, range baik. ALL = full table scan (buruk di tabel besar) |
key | Index yang dipakai | NULL berarti tidak ada index yang dipakai |
rows | Perkiraan baris yang diperiksa | Semakin kecil semakin baik |
Extra | Informasi tambahan | Waspadai Using filesort dan Using temporary; Using index adalah kabar baik |
Untuk pengukuran waktu nyata gunakan EXPLAIN ANALYZE (MySQL 8.0.18+).
Langkah 3: Perbaiki dengan pola yang tepat
1. Jangan SELECT *
Ambil hanya kolom yang kamu butuhkan. Kolom TEXT/BLOB besar yang tidak dipakai memperlambat transfer dan memenuhi memori.
SELECT id, nama, harga FROM produk WHERE kategori_id = 5;
2. Pasang index pada kolom yang dipakai untuk WHERE, JOIN, dan ORDER BY
CREATE INDEX idx_pesanan_pelanggan_tgl ON pesanan (pelanggan_id, dibuat_pada);
Index gabungan mengikuti aturan leftmost prefix: urutan kolom penting. Pembahasan lengkapnya ada di Index Database dan Pengaruhnya terhadap Performa.
3. Jangan membungkus kolom indexed dengan fungsi
Index tidak bisa dipakai jika kolom dimodifikasi:
-- Lambat: fungsi pada kolom membuat index diabaikan
SELECT * FROM pesanan WHERE YEAR(dibuat_pada) = 2025;
-- Cepat: ubah menjadi rentang
SELECT * FROM pesanan
WHERE dibuat_pada >= '2025-01-01' AND dibuat_pada < '2026-01-01';
4. Hati-hati dengan LIKE '%kata%'
Pola yang diawali wildcard tidak bisa memakai index B-tree. LIKE 'kata%' bisa. Untuk pencarian teks sungguhan gunakan FULLTEXT index (MATCH ... AGAINST) atau mesin pencari seperti Meilisearch/Elasticsearch.
5. Cocokkan tipe data
Membandingkan kolom string dengan angka (WHERE kode = 123) memaksa konversi implisit dan mematikan index. Gunakan tipe yang sama: WHERE kode = '123'.
6. Hindari OR pada kolom berbeda dan OFFSET besar
OR lintas kolom sering membuat index tidak optimal; pertimbangkan UNION. Dan pagination dengan OFFSET besar harus membaca lalu membuang banyak baris:
-- Makin ke belakang makin lambat
SELECT * FROM pesanan ORDER BY id DESC LIMIT 20 OFFSET 200000;
-- Keyset pagination: selalu cepat
SELECT * FROM pesanan WHERE id < 812345 ORDER BY id DESC LIMIT 20;
7. Gunakan EXISTS bukan COUNT(*) untuk cek keberadaan
SELECT EXISTS(SELECT 1 FROM pesanan WHERE pelanggan_id = 42);
Berhenti pada baris pertama yang ditemukan, tidak menghitung semuanya.
8. JOIN dengan benar
- Pastikan kolom JOIN sama-sama ber-index (foreign key di InnoDB otomatis diindeks).
- Batasi baris sedini mungkin dengan
WHERE. - Hindari JOIN ke banyak tabel besar sekaligus jika data yang dibutuhkan bisa dipecah.
9. Batasi hasil dan pecah pekerjaan besar
Gunakan LIMIT. Untuk memproses jutaan baris, kerjakan per batch (misalnya 1000 baris per putaran) agar tidak mengunci tabel dan menghabiskan memori.
Langkah 4: Kurangi beban dengan cache dan desain
- Cache hasil query yang mahal tetapi jarang berubah (Redis, Memcached).
- Denormalisasi terukur: simpan kolom hasil hitung seperti
jumlah_komentarjika sering dibaca dan jarang ditulis. - Tabel ringkasan untuk laporan berat, diperbarui terjadwal.
- Partisi dan arsip: pindahkan data lama yang jarang diakses.
Langkah 5: Pantau setelah perubahan
Bandingkan EXPLAIN dan waktu eksekusi sebelum dan sesudah. Pastikan perbaikan satu query tidak memperlambat query lain: setiap index baru menambah biaya penulisan (INSERT/UPDATE/DELETE) dan ruang penyimpanan.
Daftar periksa cepat
- [ ] Query dilihat lewat
EXPLAIN, tidak adatype: ALLpada tabel besar. - [ ] Hanya kolom yang dibutuhkan yang diambil.
- [ ] Kolom di
WHERE/JOIN/ORDER BYpunya index yang sesuai. - [ ] Tidak ada fungsi atau konversi tipe pada kolom ber-index.
- [ ] Pagination memakai keyset untuk data besar.
- [ ] Hasil yang mahal di-cache.
Kesimpulan
Optimasi query adalah siklus ukur → analisis dengan EXPLAIN → perbaiki → ukur lagi. Index yang tepat dan pola query yang sehat biasanya sudah memberi peningkatan puluhan hingga ratusan kali lipat, jauh sebelum kamu perlu menambah server. Untuk kasus di Laravel, lanjutkan ke Tips Optimasi Query Laravel.
Komentar (0)
Masuk / Daftar