Menulis SQL itu tidak sulit; yang sulit adalah menulisnya dengan baik.
Beekeeper Studio Adalah GUI Database Gratis & Open Source
Tool query & editor SQL terbaik yang pernah saya pakai. Semua yang saya butuhkan untuk mengelola database ada di sini. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio cepat, intuitif, dan mudah digunakan. Beekeeper mendukung banyak sekali database, dan berjalan mulus di Windows, Mac, dan Linux.
Query yang berjalan lancar saat development mulai lambat di production. ORDER BY yang terlupa menghasilkan hasil yang tidak konsisten, SELECT * yang ditulis sekilas jadi rusak saat skema berubah, dan filter yang tampak aman pada dataset kecil bisa macet total saat skalanya membesar.
Seiring waktu, Anda mulai melihat pola mana yang bertahan dan mana yang tidak.
Jadi, inilah tujuh praktik terbaik SQL dari tim di balik Beekeeper Studio, GUI database modern, open source, dan lintas platform.
🔖 Referensi Cepat: Sambil mempelajari praktik terbaik ini, simpan SQL Language Cheat Sheet kami agar Anda bisa cepat mencari SELECT, WHERE, JOIN, agregat, dan perintah SQL penting lainnya.
1. Spesifiklah — hindari SELECT *
Mengambil semua kolom dengan SELECT * memang terasa cepat dan fleksibel. Anda tidak perlu memutuskan kolom mana yang dikembalikan dan mana yang dikecualikan, dan cara ini cukup baik saat Anda masih menjelajahi dataset.
Namun fleksibilitas itu ada harganya. Saat skema berkembang atau join bertambah, SELECT * bisa menarik kolom duplikat atau tak terduga, memperlambat query, dan mempersulit debugging.
Memilih kolom secara spesifik membuat maksud query tetap jelas dan melindungi kode Anda dari kerusakan diam-diam.
-- Risky
SELECT * FROM user_profiles WHERE user_id = 42;
-- Better
SELECT user_id, display_name, avatar_url
FROM user_profiles
WHERE user_id = 42;
2. Gunakan CTE untuk menyederhanakan logika yang rumit
Subquery bertingkat memang berfungsi, tetapi cepat sekali jadi sulit dibaca. Sulit melihat apa yang difilter di mana, dan debugging biasanya berarti menggulir bolak-balik melewati lapisan tanda kurung.
Common Table Expression (klausa WITH) memungkinkan Anda memecah query menjadi langkah-langkah bernama. Setiap langkah bisa dijalankan dan diuji secara terpisah, sehingga maksudnya lebih jelas dan error lebih mudah dilacak. Ingat saja bahwa beberapa database melakukan materialisasi CTE, jadi subquery inline bisa lebih cepat dalam loop yang ketat.
-- Hard to follow
SELECT customer_id, COUNT(*)
FROM (
SELECT customer_id, created_at
FROM orders
WHERE created_at > now() - interval '7 days'
) o
GROUP BY customer_id;
-- Clearer
WITH recent_orders AS (
SELECT customer_id, created_at
FROM orders
WHERE created_at > now() - interval '7 days'
)
SELECT customer_id, COUNT(*)
FROM recent_orders
GROUP BY customer_id;
3. Beri komentar pada maksud, bukan sintaks
Komentar inline yang hanya mengulang apa yang sudah terlihat di SQL tidak banyak membantu. Konteks yang akan Anda lupakan nanti bukanlah apa yang dilakukan query, melainkan mengapa query itu ada.
Catatan singkat tentang tujuan atau penggunaan membuat kode lebih mudah ditinjau ulang atau diserahkan ke orang lain nanti. Tulislah untuk diri Anda di masa depan atau developer berikutnya yang mencoba memahami mengapa query ini penting.
-- Find users who signed up but never activated
-- Used in the weekly retention cohort report
SELECT u.id, u.email
FROM users u
LEFT JOIN events e
ON u.id = e.user_id
AND e.name = 'account_activated'
WHERE e.id IS NULL
AND u.created_at > now() - interval '7 days';
4. Buat filter Anda ramah index
Index hanya membantu jika filter Anda sargable (singkatan dari Search ARGument ABLE). Dalam praktiknya, artinya database bisa langsung menggunakan index alih-alih memindai setiap baris.
Jika Anda membungkus kolom dengan fungsi — misalnya LOWER(email) atau DATE(created_at) — optimizer tidak bisa menggunakan index. Bahkan type cast pun bisa berdampak sama. Query tetap berjalan, tetapi makin lambat seiring bertambahnya data.
-- Not sargable: disables index
WHERE LOWER(email) = 'test@example.com';
-- Sargable: uses existing index
WHERE email = 'test@example.com';
Agar filter tetap efisien, tulislah sesuai cara data disimpan. Jika Anda butuh pencocokan yang tidak peka huruf besar-kecil, simpan nilai dalam format yang konsisten atau tambahkan functional index. Untuk tanggal, filter berdasarkan rentang alih-alih mengubah kolomnya — lebih jelas dan index tetap terpakai.
-- Not sargable
WHERE DATE(created_at) = '2025-08-04';
-- Sargable
WHERE created_at >= '2025-08-04'
AND created_at < '2025-08-05';
5. Filter sebelum join
Menggabungkan semuanya dulu lalu memfilter belakangan memang menggoda, terutama saat eksplorasi atau membuat prototipe. Tetapi setiap join melipatgandakan baris, dan setiap baris yang tidak perlu membuat query lebih lambat dan lebih sulit direncanakan oleh optimizer.
Sebaliknya, persempit setiap tabel sebelum menggabungkannya. Dengan begitu, database hanya menggabungkan data yang benar-benar penting — mengurangi penggunaan memori, meningkatkan efisiensi cache, dan menjaga execution plan tetap dapat diprediksi.
-- Joins every user, even inactive ones
SELECT e.*
FROM users u
JOIN events e ON e.user_id = u.id;
-- Filter first: only active, recently seen users
WITH active_users AS (
SELECT id
FROM users
WHERE active = true
AND last_seen > now() - interval '90 days'
)
SELECT e.*
FROM active_users u
JOIN events e ON e.user_id = u.id;
6. Utamakan EXISTS daripada IN untuk memeriksa relasi
Saat memeriksa apakah baris terkait ada, IN memang bisa menyelesaikan tugasnya — sampai suatu saat tidak bisa. Ia membangun daftar nilai lengkap, membandingkan satu per satu, dan memperlakukan NULL dengan cara yang bisa menyembunyikan kecocokan yang valid.
EXISTS bekerja secara berbeda. Ia langsung mengembalikan true begitu menemukan kecocokan dan tidak terpengaruh oleh NULL di dalam subquery. Hasilnya lebih cepat sekaligus lebih andal, terutama pada dataset besar.
-- Works, but can be slower and NULL-prone
SELECT *
FROM users
WHERE id IN (SELECT user_id FROM orders);
-- Clear and efficient: stops at first match
SELECT *
FROM users u
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id
);
7. Selalu tentukan ORDER BY
SQL tidak menjamin urutan baris kecuali Anda memintanya.
Tanpa ORDER BY, database bebas mengembalikan baris dalam urutan apa pun yang paling praktis, dan urutan itu bisa berubah antar eksekusi, antar environment, atau bahkan setelah update kecil.
Mungkin terlihat stabil saat development, tetapi begitu index, execution plan, atau volume data berubah, Anda akan mulai melihat pagination yang tidak terduga atau hasil API yang tidak konsisten.
-- Looks fine until it isn't
SELECT id, name
FROM users
WHERE active = true
LIMIT 10;
-- Predictable and reproducible
SELECT id, name
FROM users
WHERE active = true
ORDER BY created_at DESC
LIMIT 10;
Merangkum semuanya
Query terbaik adalah query yang masih Anda pahami setahun kemudian. Maksudnya jelas, perilakunya dapat diprediksi, dan tanpa kejutan tersembunyi.
Itulah semangat di balik kebiasaan-kebiasaan ini. Ini adalah praktik yang kami gunakan setiap hari di Beekeeper Studio agar query tetap mudah dibaca, konsisten, dan cepat di setiap database yang kami gunakan.
Anda bisa mengambil versi PDF gratis dari panduan ini untuk disimpan atau dibagikan ke tim Anda:
Unduh 7 SQL Habits for Busy Developers
Dengan Beekeeper Studio, Anda bisa menerapkan kebiasaan ini sehari-hari menggunakan editor SQL open source modern dan lintas platform yang dirancang agar Anda tetap fokus.
- Mendukung 20+ database: Postgres, MySQL, SQLite, SQL Server, MongoDB, Redis, dan lainnya.
- Editor yang cepat dan responsif: Autocomplete yang memahami skema, query dalam tab, dan syntax highlighting.
- Alat data visual: Jelajahi tabel, edit baris, dan periksa JSON tanpa kehilangan konteks.
- Asisten AI (mengutamakan privasi): Alat coding AI yang selama ini kurang untuk database Anda — memahami skema, bekerja dengan LLM pilihan Anda, dan membantu Anda menjelajahi serta menyempurnakan query lebih cepat.