TL;DR
Index SQL adalah struktur data terpisah yang nyimpen nilai kolom dalam urutan terurut plus penunjuk ke baris aslinya, jadi database gak perlu baca seluruh tabel buat nyari satu baris. Perintahnya CREATE INDEX nama_index ON tabel(kolom). Index mempercepat SELECT tapi memperlambat INSERT, UPDATE, dan DELETE, jadi cuma pasang di kolom yang beneran sering dipakai di WHERE atau JOIN.
Index SQL adalah struktur data terpisah yang nyimpen nilai kolom dalam urutan terurut plus penunjuk ke baris aslinya. Gunanya: database gak perlu baca seluruh tabel buat nemuin satu baris.
Query yang sama, tabel yang sama. Tanpa index: 8 detik. Dengan index yang bener: 0,2 detik.
Tapi index bukan tombol ajaib. Salah pasang, kamu cuma bikin database lebih berat waktu nulis data tanpa dapet apa-apa. Aku bahas keduanya. Cara kerjanya, kapan kepake, dan 5 kondisi di mana index kamu diabaikan total sama database.
Tanpa index, database melakukan full table scan. Dia baca baris 1, cek cocok apa nggak. Baca baris 2, cek. Terus sampai baris terakhir. Tabel 5 juta baris? Dia baca 5 juta baris walau yang kamu cari cuma 1.
Dengan index, database punya salinan kolom itu yang udah terurut, disimpan dalam struktur bernama B-tree. Struktur ini bikin database bisa buang setengah kemungkinan tiap kali dia turun satu level.
Angkanya begini. Tabel 1 juta baris:
| Cara | Baris yang dibaca |
|---|---|
| Full table scan | 1.000.000 |
| B-tree index | ~20 |
Dari sejuta jadi dua puluh. Itu sebabnya bedanya bisa 40 kali lipat.
Harganya: index makan ruang disk, dan tiap kali ada baris baru masuk, index-nya harus ikut di-update.
Sintaks dasarnya sama di hampir semua database:
CREATE INDEX idx_transaksi_tanggal
ON transaksi(tanggal);
Konvensi penamaan yang enak dibaca: idx_namatabel_namakolom. Enam bulan lagi kamu bakal berterima kasih sama diri sendiri.
Index unik, selain mempercepat, dia juga nolak data dobel:
CREATE UNIQUE INDEX idx_pelanggan_email
ON pelanggan(email);
Sekali dibikin, kamu gak perlu ngapa-ngapain lagi. Database yang mutusin sendiri kapan mau pakai index itu. Kamu gak nulis "pakai index ini" di query.
Hapus index yang gak kepake:
DROP INDEX idx_transaksi_tanggal;
Composite index nempel di lebih dari satu kolom:
CREATE INDEX idx_transaksi_kota_tanggal
ON transaksi(kota, tanggal);
Urutan kolomnya menentukan segalanya. Index di atas kepake buat:
WHERE kota = 'Bandung', kepakeWHERE kota = 'Bandung' AND tanggal > '2026-01-01', kepake penuhWHERE tanggal > '2026-01-01', gak kepakeKenapa yang terakhir gak kepake? Karena index itu diurut berdasarkan kota dulu, baru tanggal di dalam tiap kota. Nyari cuma pakai tanggal artinya kamu harus lompat-lompat ke semua kota. Percuma.
Aturannya: kolom yang paling sering dipakai sendirian, taruh paling depan. Ini yang orang database sebut left-most prefix rule.
Pakai EXPLAIN. Ini yang misahin orang yang nebak-nebak dari orang yang tau.
EXPLAIN ANALYZE
SELECT kota, SUM(total) AS omzet
FROM transaksi
WHERE tanggal BETWEEN '2026-01-01' AND '2026-01-31'
GROUP BY kota;
Yang kamu cari di hasilnya:
| Yang muncul | Artinya |
|---|---|
Seq Scan / Full Table Scan | Index gak kepake. Seluruh tabel dibaca. |
Index Scan / Index Seek | Index kepake. Bagus. |
Index Only Scan | Paling cepat, semua data yang dibutuhin ada di index-nya. |
EXPLAIN ANALYZE sekalian ngejalanin query-nya dan ngasih waktu asli, bukan cuma perkiraan. Dokumentasi lengkapnya ada di manual EXPLAIN PostgreSQL.
Dataset ngulikdata toko_berkah versi besar punya 2,4 juta baris transaksi. Query laporan bulanannya begini:
SELECT kota, SUM(total) AS omzet
FROM transaksi
WHERE tanggal BETWEEN '2026-01-01' AND '2026-01-31'
GROUP BY kota
ORDER BY omzet DESC;
Tanpa index apa pun, di laptop biasa: 7,8 detik. EXPLAIN-nya nunjukin Seq Scan. 2,4 juta baris dibaca semua, padahal Januari cuma isinya 198 ribu baris.
Pasang index di kolom tanggal:
CREATE INDEX idx_transaksi_tanggal ON transaksi(tanggal);
Jalankan lagi: 0,9 detik. Sembilan kali lebih cepat. Sekarang database cuma nyentuh 198 ribu baris.
Masih bisa lebih cepat. Bikin covering index yang nyimpen semua kolom yang dipakai query ini:
CREATE INDEX idx_transaksi_laporan
ON transaksi(tanggal, kota, total);
Hasil: 0,21 detik. EXPLAIN-nya sekarang bilang Index Only Scan. Database sama sekali gak nyentuh tabel aslinya, semua yang dia butuh udah ada di index.
Dari 7,8 detik jadi 0,21 detik. 37 kali lebih cepat, dengan dua baris DDL.
Ongkosnya: index kedua makan 71 MB dan bikin INSERT sekitar 12% lebih lambat. Untuk tabel laporan yang dibaca 500 kali sehari dan ditulis 300 kali, itu tukar-tambah yang jelas menguntungkan.
Ini bagian yang paling sering bikin orang frustrasi. Index udah dibikin, query masih lambat. Lima penyebab paling umum:
-- index di kolom tanggal GAK kepake
WHERE YEAR(tanggal) = 2026
-- kepake
WHERE tanggal >= '2026-01-01' AND tanggal < '2027-01-01'
Begitu kolom dibungkus fungsi, index-nya mati. Tulis ulang jadi perbandingan rentang.
-- gak kepake
WHERE nama_produk LIKE '%gula%'
-- kepake
WHERE nama_produk LIKE 'gula%'
Index diurut dari kiri. Kalau kiri-nya bebas, dia gak bisa nyari apa-apa. Untuk pencarian kata di tengah, kamu butuh full-text index, bukan B-tree biasa.
Index di kolom status yang isinya cuma 'aktif' dan 'nonaktif'? Percuma. Kalau 50% baris nilainya 'aktif', database ngitung bahwa baca seluruh tabel malah lebih cepat daripada bolak-balik lewat index.
Istilahnya low cardinality. Aturan kasarnya: kalau satu nilai nyakup lebih dari 15-20% tabel, index-nya bakal diabaikan.
Tabel 500 baris? Database baca semuanya dalam sekejap. Index cuma nambah kerjaan. Optimizer bakal ngabaikan index kamu, dan dia bener.
-- kolom kode_produk bertipe VARCHAR, tapi dibandingin sama angka
WHERE kode_produk = 1042 -- index bisa mati
WHERE kode_produk = '1042' -- aman
Konversi tipe implisit sering matiin index tanpa ngasih peringatan apa pun.
Gak ada angka pasti, tapi patokan yang aku pakai: 5 index per tabel udah banyak. Di atas itu, cek ulang.
Tiap index nambah beban di tiap INSERT, UPDATE, dan DELETE. Tabel dengan 12 index bikin satu INSERT jadi 13 pekerjaan.
Urutan prioritas kalau kamu baru mulai:
Kalau query kamu masih lambat setelah semua ini, masalahnya mungkin bukan di index. Cek dulu struktur query-nya. Kadang bikin VIEW atau nulis ulang subquery lebih ngefek dari nambah index.
Index adalah struktur data terpisah yang nyimpen nilai satu kolom (atau beberapa kolom) dalam keadaan terurut, plus penunjuk ke lokasi baris aslinya. Waktu kamu nyari data, database bisa lompat langsung ke lokasi yang bener lewat index, bukan baca satu-satu semua baris dari awal. Efeknya di tabel besar bisa dari beberapa detik jadi milidetik.
Kolom yang sering muncul di WHERE, JOIN, dan ORDER BY. Kolom foreign key hampir selalu layak diindex soalnya dipakai buat JOIN terus-terusan. Kolom tanggal juga, soalnya laporan biasanya nyaring per periode. Yang gak layak: kolom dengan sedikit nilai unik kayak status atau gender, dan kolom yang jarang dipakai buat nyaring.
Tiap kali kamu INSERT, UPDATE, atau DELETE, database harus update semua index yang nempel di tabel itu. Satu tabel dengan 8 index berarti 8 pekerjaan tambahan tiap kali ada baris masuk. Di tabel yang isinya jarang dibaca tapi sering ditulis, index yang kebanyakan bikin proses tulis jauh lebih berat tanpa manfaat yang sepadan.
Pakai EXPLAIN atau EXPLAIN ANALYZE di depan query kamu. Hasilnya nunjukin rencana eksekusi database. Kalau kamu lihat kata Seq Scan atau Full Table Scan, artinya index gak kepake dan database baca seluruh tabel. Kalau muncul Index Scan atau Index Seek, index kamu kerja. EXPLAIN ANALYZE sekalian ngasih waktu eksekusi asli.
Composite index adalah index yang nempel di beberapa kolom sekaligus, misal (kota, tanggal). Urutan kolomnya penting banget. Index itu kepake buat query yang nyaring kota doang, atau kota plus tanggal. Tapi gak kepake buat query yang cuma nyaring tanggal. Taruh kolom yang paling sering dipakai sendirian di posisi paling depan.
Yang perlu kamu inget:
EXPLAIN dulu sebelum bikin index. Tebakan kamu soal query mana yang lambat sering meleset.% matiin index kamu diam-diam.Ambil query paling lambat di kerjaan kamu, jalanin EXPLAIN ANALYZE, dan lihat apakah muncul Seq Scan. Kalau iya, kamu baru aja nemu perbaikan 10 kali lipat yang cuma butuh satu baris SQL.
Lanjut: latihan query di referensi fungsi JOIN, atau baca apa itu query optimization di glosarium ngulikdata.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Analisa per kuartal, hari kerja, atau musim jadi ribet kalau tiap query ngitung ulang atribut tanggal. Tabel kalender nyimpen semua atribut itu sekali, biar tinggal di-JOIN.
Laporan penjualan harian sering bolong di hari tanpa transaksi. Ini cara bikin deret tanggal lengkap di SQL biar tiap hari muncul, walau nilainya nol.
Struktur organisasi tersimpan sebagai kolom id_atasan yang saling nunjuk. Ini cara narik rantai jabatan, hitung total bawahan, dan span of control cuma pakai SQL.