
Menulis query SQL yang berfungsi itu satu hal, tapi menulis query yang efisien dan scalable itu hal lain. Jika query ditulis dengan buruk, hasilnya bisa membuat aplikasi lambat, membuat pengguna frustrasi, bahkan bisa menyebabkan crash pada sistem produksi.
Berikut adalah 20 kesalahan umum yang sering dilakukan dan cara menghindarinya:
Kesalahan 1
Masalah: Mengambil semua kolom tanpa pertimbangan.
Kenapa buruk: Meningkatkan I/O, penggunaan memori, dan memperlambat JOIN.
Solusi: Pilih hanya kolom yang diperlukan.
SELECT name, email FROM users;Kesalahan 2
Masalah: Tidak ada indeks pada kolom yang sering digunakan.
Dampak: Query jadi lambat karena melakukan full table scan.
Solusi: Tambahkan indeks pada kolom yang digunakan di WHERE, JOIN, atau ORDER BY.
CREATE INDEX idx_users_email ON users(email);Kesalahan 3
Masalah: Menambahkan indeks berlebihan.
Dampak: Memperlambat proses INSERT/UPDATE dan memperbesar ukuran database.
Solusi: Tambahkan indeks hanya pada query penting. Gunakan EXPLAIN untuk analisis.
Kesalahan 4
Masalah: Memakai fungsi seperti UPPER() di kolom indexed dalam WHERE.
Dampak: Index tidak digunakan.
Solusi: Hindari fungsi di kolom indexed.
-- Hindari
WHERE UPPER(email) = 'USER@EXAMPLE.COM'
-- Lebih baik
WHERE email = LOWER('user@example.com')Kesalahan 5
Masalah: JOIN tabel besar tanpa kondisi filter.
Dampak: Memperlambat query secara drastis.
Solusi: Filter data sebelum JOIN.
SELECT ...
FROM large_table lt
JOIN small_table st ON lt.id = st.id
WHERE st.status = 'active';Kesalahan 6
Masalah: Subquery dengan IN bisa lambat.
Solusi: Gunakan EXISTS untuk subquery korelatif.
-- Hindari
SELECT name FROM users WHERE id IN (SELECT user_id FROM logins);
-- Lebih baik
SELECT name FROM users u WHERE EXISTS (
SELECT 1 FROM logins l WHERE l.user_id = u.id
);Kesalahan 7
Masalah: Mengambil jutaan baris sekaligus.
Dampak: Membebani jaringan dan memori.
Solusi: Gunakan pagination dengan LIMIT dan OFFSET.
SELECT ...
FROM large_table lt
LIMIT 100Kesalahan 8
Masalah: Menyimpan angka sebagai VARCHAR atau tanggal sebagai string.
Dampak: Perbandingan lambat dan boros ruang.
Solusi: Gunakan tipe data yang tepat: INT, DATE, DATETIME.
Kesalahan 9
Masalah: Subquery yang dijalankan per baris.
Dampak: Eksekusi sangat lambat.
Solusi: Gunakan JOIN atau WITH (CTE).
WITH order_counts AS (
SELECT user_id, COUNT(*) AS count FROM orders GROUP BY user_id
)
SELECT u.name, oc.count
FROM users u
LEFT JOIN order_counts oc ON u.id = oc.user_id;Kesalahan 10
Masalah: DISTINCT sering digunakan untuk menutupi kesalahan JOIN.
Solusi: Perbaiki logika JOIN, bukan tambal sulam.
Kesalahan 11
Masalah: Query berat dijalankan berulang kali.
Solusi: Gunakan materialized view atau caching di level aplikasi.
Kesalahan 12
Masalah: Banyak OR menghambat penggunaan index.
Solusi: Gunakan UNION atau pecah query.
Kesalahan 13
Masalah: Terlalu banyak CTE membuat query lambat.
Solusi: Inline logic atau pecah query.
Kesalahan 14
Masalah: Query dijalankan tanpa analisis.
Solusi: Selalu gunakan EXPLAIN untuk melihat rencana eksekusi.
Kesalahan 15
Masalah: Tidak memanfaatkan kolom partisi di WHERE.
Dampak: Membaca semua partisi.
Kesalahan 16
Masalah: JOIN tanpa kondisi, hasil miliaran baris.
Solusi: Pastikan semua JOIN punya kondisi yang benar.
Kesalahan 17
Masalah: JOIN lebih dari 10 tabel.
Solusi: Pecah query atau buat view.
Kesalahan 18
Masalah: Sorting pada tabel besar tanpa index.
Solusi: Buat index pada kolom yang sering diurutkan.
Kesalahan 19
Masalah: Trigger yang melakukan proses besar.
Solusi: Pindahkan ke proses asynchronous atau job queue.
Kesalahan 20
Masalah: Query tabel besar dengan data yang sudah tidak relevan.
Solusi: Arsipkan atau hapus data lama secara rutin.
INT vs VARCHAR)IS NULL (bukan = NULL)Mengoptimalkan SQL bukan hanya soal query yang berjalan, tapi query yang skalabel. Selalu pikirkan dari sudut pandang database engine: seberapa banyak data yang harus dibaca, diurutkan, atau digabung?
Gunakan EXPLAIN, monitor query lambat, dan lakukan profiling secara berkala. Perubahan kecil = peningkatan besar!