Bekerja dengan JSONB di PostgreSQL
TL;DR
JSONB di PostgreSQL adalah tipe kolom yang nyimpen data JSON dalam bentuk biner terurai, jadi lebih cepat dibaca dan bisa diindeks dibanding tipe JSON biasa. Buat ngambil nilai, operator -> ngasih hasil JSON dan ->> ngasih teks biasa, sedangkan operator @> ngecek satu JSONB memuat pasangan tertentu. Query JSONB yang sering nyaring isi sebaiknya dibantu GIN index biar tetap cepat di tabel besar.
JSONB di PostgreSQL nyimpen data JSON dalam bentuk biner yang udah terurai, jadi lebih cepat dibaca dan bisa diindeks. Ini cara nyimpen data semi-terstruktur tanpa keluar dari database relasional.
Kepakai waktu strukturnya nggak seragam. Log transaksi yang field-nya beda tiap tipe, atribut produk yang berubah-ubah, atau respons API mentah.
Aku bakal bahas beda JSON sama JSONB, operator buat ngambil nilai, cara ngecek isi, dan cara bikin query-nya tetap cepat pakai GIN index.
Apa itu JSONB di PostgreSQL?
JSONB adalah tipe kolom yang nyimpen dokumen JSON dalam format biner terurai. Beda dari tipe JSON biasa yang nyimpen teks apa adanya, JSONB udah diproses jadi struktur, jadi PostgreSQL nggak perlu baca ulang teksnya tiap query. Hasilnya lebih cepat dan bisa diindeks.
Bayarannya, JSONB nggak nyimpen spasi asli dan bisa ngubah urutan key. Buat analisa, itu nggak masalah.
Apa beda JSON dan JSONB?
| Aspek | JSON | JSONB |
|---|---|---|
| Penyimpanan | Teks apa adanya | Biner terurai |
| Kecepatan baca | Lebih lambat | Lebih cepat |
| Bisa diindeks | Terbatas | Iya, pakai GIN |
| Urutan key | Dipertahankan | Bisa berubah |
Buat hampir semua kebutuhan, pilih JSONB. JSON biasa cuma pas kalau kamu wajib nyimpen teks aslinya persis.
Gimana cara ekstrak nilai dari JSONB?
Dua operator paling sering dipakai: -> ngasih hasil JSON, ->> ngasih teks biasa.
SELECT
data->'pelanggan' AS pelanggan_json,
data->>'metode_bayar' AS metode,
(data->>'total')::numeric AS total
FROM transaksi;
Pakai ->> kalau mau langsung bandingin atau ubah ke angka, karena hasilnya teks. Pakai -> kalau mau nyusuri JSON lebih dalam. Buat masuk ke nilai bersarang, ada operator jalur #>> yang nerima daftar key.
SELECT data#>>'{pelanggan,kota}' AS kota
FROM transaksi;
Gimana cara nyaring baris berdasarkan isi JSONB?
Operator containment @> ngecek satu JSONB memuat pasangan tertentu. Ini cara paling bersih buat nyaring.
SELECT id
FROM transaksi
WHERE data @> '{"metode_bayar": "qris"}';
Kamu juga bisa nyaring pakai hasil ->>, misalnya WHERE data->>'status' = 'lunas'. Bedanya, @> lebih cocok dibantu index dan enak buat ngecek beberapa pasangan sekaligus.
Gimana cara bikin dan menggabung JSONB?
jsonb_build_object nyusun JSONB dari pasangan key dan nilai. jsonb_agg ngumpulin banyak baris jadi satu array JSON, mirip ARRAY_AGG di array biasa.
SELECT jsonb_build_object(
'produk', produk,
'qty', qty
) AS baris_json
FROM item_transaksi;
SELECT id_transaksi,
jsonb_agg(produk) AS daftar_produk
FROM item_transaksi
GROUP BY id_transaksi;
Buat kebalikannya, jsonb_array_elements mecah array JSON jadi baris-baris, mirip UNNEST.
Gimana bikin query JSONB tetap cepat?
Di tabel besar, nyaring isi JSONB tanpa index bikin PostgreSQL buka tiap dokumen satu per satu. Bikin GIN index biar operator @> jalan cepat.
CREATE INDEX idx_transaksi_data
ON transaksi USING GIN (data);
Setelah ini, query dengan @> ngambil jalan pintas lewat index, nggak scan seluruh tabel. Konsep index ini mirip teknik agregasi yang aku bahas di artikel STRING_AGG soal menjaga query tetap ringkas dan cepat.
Contoh kasus: log transaksi Toko Berkah
Toko Berkah, UMKM kelontong di dataset latihan ngulikdata, nyimpen tiap transaksi digital di kolom JSONB bernama data. Isinya metode bayar, status, total, dan detail pelanggan yang formatnya beda-beda tergantung kanal. Ada 12.480 transaksi selama 2025.
Pemilik mau tau berapa transaksi pakai QRIS dan berapa totalnya:
SELECT COUNT(*) AS jumlah,
SUM((data->>'total')::numeric) AS total_qris
FROM transaksi
WHERE data @> '{"metode_bayar": "qris"}';
Hasilnya, 3.640 transaksi (29% dari total) pakai QRIS dengan nilai Rp214.300.000. Setelah GIN index dipasang, query ini yang tadinya scan penuh jadi kelar dalam sekejap. Angka 29% ini yang bikin pemilik pasang QRIS di kasir kedua, karena kanal ini tumbuh paling cepat sepanjang tahun.
Kesalahan umum saat pakai JSONB
1. Ketuker -> dan ->>
-> ngasih JSON, ->> ngasih teks. Kalau kamu bandingin hasil -> dengan teks biasa, perbandingannya nggak jalan seperti yang diharap. Buat filter dan konversi angka, hampir selalu ->> yang benar.
2. Lupa cast sebelum hitung
Nilai dari ->> selalu teks, walau isinya angka. Ngitung SUM langsung bakal error atau salah. Cast dulu pakai ::numeric, kayak (data->>'total')::numeric.
3. Naruh data terstruktur di JSONB
JSONB buat data yang strukturnya berubah-ubah. Kalau semua baris punya field sama dan tetap, kolom biasa lebih cepat dan lebih gampang di-JOIN. JSONB fleksibel, tapi bukan alasan buat naruh semua di satu kolom.
FAQ
Apa beda JSON dan JSONB di PostgreSQL?
JSON nyimpen teks apa adanya persis kayak yang kamu masukin, termasuk spasi dan urutan key. JSONB nyimpennya dalam bentuk biner yang udah diurai, jadi urutan key bisa berubah dan spasi hilang. Bayarannya, JSONB lebih cepat waktu dibaca dan bisa diindeks. Buat hampir semua kebutuhan analisa, JSONB pilihan yang benar. JSON biasa cuma pas kalau kamu wajib nyimpen teks aslinya utuh.
Apa beda operator -> dan ->> di JSONB?
Operator -> ngambil elemen dan ngembaliinnya tetap sebagai JSON, sedangkan ->> ngambil elemen dan ngembaliinnya sebagai teks biasa. Kalau kamu mau langsung bandingin nilai atau ubah ke angka, pakai ->> biar dapat teks. Kalau kamu mau lanjut nyusuri JSON yang lebih dalam, pakai -> biar hasilnya masih bertipe JSON dan bisa dioperasikan lagi.
Kapan JSONB butuh GIN index?
Pakai GIN index kalau kamu sering nyaring baris berdasarkan isi JSONB, misalnya nyari transaksi dengan metode bayar tertentu di tabel jutaan baris. Tanpa index, PostgreSQL harus buka tiap JSONB satu per satu. GIN index bikin operator containment @> jalan cepat. Kalau kolom JSONB cuma disimpan dan jarang difilter, index-nya nggak perlu.
Kapan sebaiknya pakai JSONB, bukan kolom biasa?
Pakai JSONB kalau struktur datanya berubah-ubah atau atributnya nggak seragam antar baris, misalnya log kejadian yang tiap tipe punya field beda. Kalau semua baris punya kolom yang sama dan tetap, kolom biasa lebih baik karena lebih cepat, lebih ketat tipenya, dan gampang di-JOIN. JSONB fleksibel, tapi jangan dipakai buat data yang sebenernya rapi dan terstruktur.
Penutup
- JSONB nyimpen JSON dalam bentuk biner yang cepat dibaca dan bisa diindeks, pilih ini dibanding JSON biasa.
- Pakai ->> buat ambil teks, -> buat nyusuri lebih dalam, dan @> buat nyaring isi.
- Buat tabel besar yang sering difilter, pasang GIN index biar query-nya tetap cepat.
Coba sekarang: bikin tabel kecil dengan kolom JSONB berisi detail transaksi, lalu hitung total per metode bayar pakai @> dan cast ::numeric.
Mau pendalaman? Baca dulu fungsi array di PostgreSQL yang konsepnya berdekatan. Referensi fungsi ada di jsonb_build_object dan jsonb_array_elements, plus dokumentasi resmi tipe JSON PostgreSQL.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel terkait
Composite Index di SQL: Cara Kerja dan Urutan Kolom
Composite index itu index atas beberapa kolom sekaligus. Urutan kolomnya nentuin query mana yang kebantu, lewat aturan leftmost prefix.
Menghitung Stickiness (DAU/MAU) di SQL
Stickiness ngukur seberapa sering user balik lagi. Ini cara hitung DAU, MAU, dan rasio stickiness pakai SQL, plus contoh aplikasi UMKM.
Menghitung DAU dan MAU dengan SQL
DAU dan MAU dua metrik wajib buat produk digital. Ini cara hitungnya pakai SQL, lengkap query DISTINCT, per bulan, sampai rasio stickiness.