Surrogate Key vs Natural Key untuk Analis Data
TL;DR
Natural key adalah kolom yang udah ada di data bisnis dan unik secara alami, kayak NIK atau kode SKU. Surrogate key adalah ID buatan tanpa makna bisnis, biasanya angka urut atau UUID, yang dibikin database khusus buat jadi identitas baris. Praktik paling aman buat analis: pakai surrogate key sebagai primary key, lalu pasang unique constraint di natural key-nya supaya duplikat tetap ketahan.
Natural key adalah kolom yang udah ada di data bisnis dan unik secara alami, misalnya NIK atau kode SKU. Surrogate key adalah ID buatan yang dibikin database dan nggak punya makna bisnis apa pun.
Pilihan antara keduanya kelihatan sepele waktu tabelnya masih 200 baris. Setahun kemudian, waktu ada pelanggan ganti email dan tiga tabel ikut rusak, baru kerasa.
Di bawah ini bedanya, kapan masing-masing dipakai, dan pola yang aku pakai di hampir semua proyek.
Apa itu natural key dan surrogate key?
Natural key adalah kolom atau gabungan kolom yang nilainya berasal dari dunia nyata dan udah unik dengan sendirinya. Contohnya nomor invoice, kode SKU, NPWP, atau kode pos. Surrogate key adalah nilai yang dibikin sistem khusus buat jadi identitas baris, biasanya angka urut atau UUID, dan nggak punya arti di luar database.
Bedanya paling gampang dilihat dari satu pertanyaan: kalau data ini dicetak di kertas dan dikasih ke orang bisnis, dia ngerti nggak nilai itu artinya apa?
Kode BRK-014 dia ngerti. Angka 4471 nggak berarti apa-apa buat dia, dan memang itu maksudnya.
Apa bedanya secara praktis?
| Aspek | Natural key | Surrogate key |
|---|---|---|
| Asal nilai | Dari data bisnis | Dibikin database |
| Makna | Bisa dibaca manusia | Nggak ada artinya |
| Stabilitas | Bisa berubah kapan aja | Nggak pernah berubah |
| Ukuran | Sering panjang, tipe teks | Ringkas, biasanya bigint |
| Join | Lebih lambat kalau teks panjang | Cepat, indeksnya kecil |
| Gabung banyak sumber | Bentrok kalau format beda | Aman, tiap sumber dipetakan |
| Risiko privasi | Tinggi kalau isinya NIK atau email | Rendah, nilainya nggak bermakna |
| Query ad hoc | Enak, nggak perlu join | Perlu join ke tabel dimensi |
Baris stabilitas itu yang paling sering nyakitin. Manajemen ganti format kode produk dari BRK-014 jadi ACC-BRK-014, dan tiba-tiba semua tabel yang nunjuk ke situ harus di-update bareng.
Kapan sebaiknya pakai surrogate key?
Pakai surrogate key kalau nilai bisnisnya bisa berubah, kalau kamu gabungin data dari lebih dari satu sistem, atau kalau natural key-nya berupa data pribadi. Ini juga wajib di tabel dimensi data warehouse yang harus nyimpen riwayat perubahan.
Di PostgreSQL, cara paling bersih bikinnya lewat identity column:
CREATE TABLE pelanggan (
pelanggan_sk BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
email TEXT NOT NULL,
nama TEXT NOT NULL,
kota TEXT,
CONSTRAINT uq_pelanggan_email UNIQUE (email)
);
Perhatiin barisnya: primary key-nya surrogate, tapi email tetap dikasih unique constraint. Jadi kamu dapet dua-duanya, identitas yang stabil plus perlindungan dari data dobel.
GENERATED ALWAYS AS IDENTITY itu cara standar SQL, lebih rapi dari tipe serial yang lama. Penjelasan lengkapnya ada di dokumentasi resmi PostgreSQL.
Kapan natural key masih pilihan yang bener?
Natural key cocok buat tabel referensi yang kodenya udah baku dan dikontrol pihak luar. Kode provinsi dari BPS, kode mata uang ISO, atau kode bandara IATA nggak bakal berubah, jumlahnya sedikit, dan jauh lebih enak dibaca langsung di hasil query tanpa perlu join.
CREATE TABLE provinsi (
kode_prov CHAR(2) PRIMARY KEY,
nama_prov TEXT NOT NULL
);
Tabel begini isinya 38 baris dan hampir nggak pernah berubah. Nambahin surrogate key di sini cuma bikin query kamu satu join lebih panjang tanpa manfaat.
Satu lagi kasus yang sah: tabel jembatan many to many. Primary key-nya gabungan dua foreign key, dan itu udah cukup.
Contoh kasus: data pelanggan toko_berkah dari dua sistem
Toko Berkah punya data pelanggan di dua tempat: sistem kasir toko fisik dan platform toko online. Dua-duanya pakai email sebagai identitas pelanggan.
Waktu digabung, ketahuan masalahnya.
SELECT email, COUNT(*) AS jumlah
FROM pelanggan_mentah
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY jumlah DESC;
Hasil di dataset latihan ngulikdata: dari 8.417 baris pelanggan gabungan, 312 email muncul lebih dari sekali. Sebagian karena orangnya beneran daftar dua kali. Sebagian lagi karena kasir ngisi email default tokoberkah@gmail.com buat pelanggan yang nggak mau ngasih email, dan itu kepakai 148 kali.
Kalau email dijadiin primary key, proses impornya gagal total di baris ke-59. Kalau dipaksa pakai upsert, 148 transaksi dari orang berbeda bakal nempel ke satu pelanggan yang sama.
Solusinya: surrogate key sebagai identitas, plus tabel pemetaan yang nyimpen ID asli dari tiap sumber.
CREATE TABLE pelanggan_sumber (
pelanggan_sk BIGINT NOT NULL REFERENCES pelanggan (pelanggan_sk),
sistem_asal TEXT NOT NULL,
id_di_sumber TEXT NOT NULL,
PRIMARY KEY (sistem_asal, id_di_sumber)
);
Dengan pola ini, kamu tetap bisa nelusuri satu baris balik ke sistem asalnya waktu ada selisih angka. Ini bagian dari kerapian ETL yang biasanya baru kerasa gunanya waktu ada audit.
Kenapa data warehouse hampir selalu pakai surrogate key?
Karena tabel dimensi harus nyimpen riwayat. Kalau pelanggan pindah dari Bandung ke Jakarta, laporan bulan lalu harus tetap nunjukkin Bandung. Artinya kamu butuh dua baris untuk satu pelanggan yang sama, dan natural key-nya bakal kembar di dua baris itu.
pelanggan_sk | customer_id | kota | valid_from | valid_to | is_current
4471 | C001 | Bandung | 2024-01-05 | 2025-06-30 | FALSE
8892 | C001 | Jakarta | 2025-07-01 | 9999-12-31 | TRUE
Tabel fakta nyimpen pelanggan_sk, bukan customer_id. Jadi transaksi Maret 2025 otomatis nyambung ke baris Bandung, dan angka historisnya nggak berubah waktu pelanggannya pindah.
Pola lengkapnya aku bahas di panduan SCD Type 2 di SQL.
Kesalahan umum soal primary key
- Nganggep natural key pasti unik selamanya. Cek dulu pakai GROUP BY dan HAVING sebelum nentuin. Keunikan yang berlaku di satu sistem sering langsung rusak waktu digabung.
- Pakai nomor telepon atau email sebagai primary key. Dua-duanya bisa diganti pemiliknya, dan dua-duanya data pribadi.
- Bikin surrogate key tapi lupa unique constraint di natural key-nya. Hasilnya duplikat masuk tanpa ada yang ngeblok, dan angka laporan jadi lebih besar dari kenyataan.
- Natural key gabungan lima kolom. Setiap tabel yang nunjuk ke situ harus nyimpen lima kolom juga. Indeksnya jadi berat.
- Nampilin surrogate key ke pengguna akhir. Angka 4471 nggak berarti apa-apa buat tim penjualan. Tampilkan kode bisnisnya di laporan.
Nomor tiga yang paling sering aku temuin. Duplikatnya nggak bikin error apa-apa, cuma bikin total penjualan naik diam-diam. Bikin pengecekan kualitas data yang jalan tiap kali data baru masuk, dan pola insert amannya ada di panduan upsert dan merge.
FAQ
Mana yang lebih bagus, surrogate key atau natural key?
Buat tabel operasional dan tabel dimensi di data warehouse, surrogate key hampir selalu lebih aman karena nilainya nggak pernah berubah. Natural key masih pas buat tabel referensi yang kodenya udah baku dan dikontrol pihak luar, kayak kode provinsi BPS. Kombinasi paling umum: surrogate key jadi primary key, natural key dikasih unique constraint.
Boleh nggak pakai email sebagai primary key?
Sebaiknya jangan. Email itu bisa diganti pelanggan kapan aja, dan begitu diganti kamu harus update semua tabel yang nunjuk ke situ. Email juga data pribadi, jadi nyebar ke banyak tabel bikin kerjaan kamu makin berat waktu ada permintaan hapus data. Simpan email di satu tabel dengan unique constraint, sisanya pakai surrogate key.
Pilih integer atau UUID buat surrogate key?
Integer lebih kecil, lebih cepat di-join, dan enak dibaca waktu debugging. UUID lebih pas kalau ID-nya dibikin di banyak sistem sekaligus atau bakal muncul di URL publik. Buat tabel analitik yang isinya jutaan baris dan sering di-join, integer biasanya menang dari sisi kecepatan.
Gimana cara ngecek natural key saya beneran unik?
Jalankan GROUP BY di kolom itu lalu saring pakai HAVING COUNT(*) > 1. Kalau hasilnya kosong, aman untuk sekarang. Tapi ulangi pengecekan ini tiap kali ada sumber data baru masuk, soalnya keunikan yang berlaku di satu sistem sering langsung rusak begitu digabung sama sistem lain.
Kenapa data warehouse selalu pakai surrogate key?
Karena tabel dimensi harus bisa nyimpen riwayat. Kalau satu pelanggan pindah kota, kamu butuh dua baris untuk pelanggan yang sama: versi lama dan versi baru. Natural key nggak bisa dipakai sebagai primary key di situ karena nilainya kembar. Surrogate key ngasih tiap versi identitas sendiri.
Pola yang aman dipakai default
Surrogate key jadi primary key, natural key dikasih unique constraint, dan simpan ID asli tiap sumber di tabel pemetaan terpisah.
Tiga hal itu nutup hampir semua kasus yang bakal kamu temuin, dan biayanya cuma satu kolom tambahan.
Coba cek satu tabel di database kamu sekarang: jalanin GROUP BY di kolom yang kamu anggap unik, lihat ada duplikat atau nggak. Kalau kamu masih ngasah dasar SQL-nya, latihan soalnya ada di kumpulan latihan SQL tingkat menengah.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel terkait
Cara Membuat Pivot Dinamis di SQL (Panduan 2026)
Pivot dinamis di SQL ngubah baris jadi kolom tanpa kamu hardcode nama kolomnya. Ini cara bikinnya pakai CASE WHEN dan versi yang kolomnya ngikut data.
Menghitung YTD, QTD, dan MTD di SQL (Panduan 2026)
YTD, QTD, dan MTD ngukur total dari awal tahun, kuartal, atau bulan sampai hari ini. Ini cara ngitungnya di SQL pakai DATE_TRUNC, plus satu query gabungan.
Gap and Island Analysis di SQL
Gap and island analysis di SQL nyari deret data yang berturut-turut (island) dan celah yang bolong (gap). Cocok buat hitung streak login atau cari tanggal transaksi yang hilang.