TL;DR
Materialized view adalah objek database yang nyimpen hasil sebuah query secara fisik ke disk, beda dengan view biasa yang ngitung ulang tiap kali dipanggil. Karena hasilnya udah jadi, query yang berat bisa dibaca dalam milidetik. Konsekuensinya: datanya bisa basi sampai kamu jalanin REFRESH, dan dia makan storage.
Materialized view adalah objek database yang nyimpen hasil sebuah query secara fisik ke disk, jadi waktu dibaca dia gak perlu ngitung ulang apa pun.
View biasa itu kayak resep. Tiap kali dibuka, dimasak lagi dari awal. Materialized view itu masakannya yang udah jadi dan disimpan di kulkas.
Di sini kamu bakal tau bedanya secara teknis, angka nyata dari dataset toko_berkah, cara REFRESH tanpa bikin dashboard nge-freeze, dan kapan materialized view justru bikin masalah baru.
Materialized view adalah tabel hasil query yang disimpan permanen di disk dan bisa dibaca kayak tabel biasa. Isinya gak otomatis ikut berubah waktu tabel sumbernya diupdate. Kamu harus jalanin perintah REFRESH buat nyegerin lagi datanya.
Bandingin sama view biasa yang cuma nyimpen teks querynya. View gak makan storage, tapi tiap dibaca dia jalanin ulang semua JOIN dan GROUP BY dari nol.
| Aspek | View | Materialized view |
|---|---|---|
| Yang disimpan | Teks query | Hasil query |
| Storage | Nyaris nol | Sebesar hasilnya |
| Kecepatan baca | Selambat query aslinya | Secepat baca tabel |
| Kesegaran data | Selalu terkini | Sesuai REFRESH terakhir |
| Bisa di-index | Gak | Bisa |
Baris terakhir itu yang sering dilupain. Materialized view bisa dikasih index, dan itu yang bikin dia bisa secepat tabel biasa.
Tiga kondisi yang bikin dia masuk akal.
Querynya berat dan dibaca berkali-kali. Dashboard yang dibuka 200 orang tiap pagi, isinya query dengan 4 JOIN dan agregasi jutaan baris. Hitung sekali, baca 200 kali.
Data sumbernya jarang berubah. Ringkasan penjualan kemarin gak bakal berubah lagi hari ini. Buat apa dihitung ulang tiap ada yang buka dashboard.
Data basi beberapa jam masih bisa diterima. Laporan omzet bulanan gak butuh presisi detik. Kalau angkanya telat 1 jam, gak ada yang rugi.
Kalau ketiganya kena, materialized view biasanya keputusan yang bener.
Dataset toko_berkah di Ngulik Data punya 1,4 juta baris transaksi dari 6 cabang UMKM. Dashboard omzet hariannya narik data lewat query ini.
SELECT
t.tanggal,
c.nama_cabang,
COUNT(*) AS jumlah_transaksi,
SUM(t.qty * t.harga_jual) AS omzet,
SUM(t.qty * (t.harga_jual - p.hpp)) AS margin
FROM transaksi t
JOIN produk p ON p.kode = t.kode_produk
JOIN cabang c ON c.id = t.cabang_id
WHERE t.status = 'selesai'
GROUP BY t.tanggal, c.nama_cabang;
Waktu eksekusinya 8,4 detik. Dashboard dibuka rata-rata 40 kali per hari. Total 5,6 menit CPU kebuang tiap hari cuma buat ngitung ulang angka yang sama.
Bikin materialized view-nya.
CREATE MATERIALIZED VIEW mv_penjualan_harian AS
SELECT
t.tanggal,
c.nama_cabang,
COUNT(*) AS jumlah_transaksi,
SUM(t.qty * t.harga_jual) AS omzet,
SUM(t.qty * (t.harga_jual - p.hpp)) AS margin
FROM transaksi t
JOIN produk p ON p.kode = t.kode_produk
JOIN cabang c ON c.id = t.cabang_id
WHERE t.status = 'selesai'
GROUP BY t.tanggal, c.nama_cabang;
Hasilnya cuma 2.190 baris. Tiga tahun data harian dikali 6 cabang.
Kasih index biar filter tanggalnya makin ngebut.
CREATE UNIQUE INDEX idx_mv_penjualan
ON mv_penjualan_harian (tanggal, nama_cabang);
Sekarang dashboardnya baca dari sini.
SELECT nama_cabang, SUM(omzet) AS omzet_bulan
FROM mv_penjualan_harian
WHERE tanggal >= DATE '2026-03-01'
GROUP BY nama_cabang
ORDER BY omzet_bulan DESC;
Waktu eksekusi: 0,2 detik. Dari 8,4 detik jadi 0,2 detik, sekitar 42 kali lebih cepat.
Yang berubah bukan kecerdasan querynya. Kerjaan beratnya cuma dipindah dari jam sibuk ke jam 2 pagi.
REFRESH biasa ngunci materialized view selama proses berjalan. Kalau ada orang yang lagi buka dashboard, dia bakal nunggu.
REFRESH MATERIALIZED VIEW mv_penjualan_harian;
-- Pembaca lain kena lock sampai selesai
PostgreSQL punya opsi yang lebih sopan.
REFRESH MATERIALIZED VIEW CONCURRENTLY mv_penjualan_harian;
-- Pembaca tetap bisa akses data lama selama refresh jalan
Syaratnya: materialized view-nya harus punya UNIQUE INDEX. Itu alasan kenapa index tadi bukan opsional.
Buat penjadwalan, cara paling umum di PostgreSQL pakai ekstensi pg_cron.
SELECT cron.schedule(
'refresh-penjualan',
'0 2 * * *',
$$REFRESH MATERIALIZED VIEW CONCURRENTLY mv_penjualan_harian$$
);
Jam 2 pagi, tiap hari. Penjelasan sintaks lengkapnya ada di dokumentasi resmi PostgreSQL untuk CREATE MATERIALIZED VIEW.
Aku pernah lihat tim nge-set refresh tiap 5 menit buat dashboard yang dibuka 3 kali sehari. Query refresh-nya 8 detik, jadi database ngabisin 38 menit CPU per hari buat ngelayanin 3 pageview.
Tanpa itu, kamu gak bisa pakai CONCURRENTLY, dan tiap refresh bakal ngunci dashboard buat semua orang.
Stok gudang, saldo rekening, kursi bioskop. Data basi 5 menit di kasus kayak gini bisa bikin barang kejual dua kali. Pakai index di tabel aslinya, bukan materialized view.
Tiap materialized view yang idle tetap makan storage dan tetap ikut antre refresh. Setiap kuartal, cek mana yang beneran dibaca dan hapus sisanya.
Dua puluh materialized view yang refresh bareng jam 2 pagi bikin database kamu megap-megap. Kasih jarak 5-10 menit antar job.
View cuma nyimpen teks querynya dan dijalanin ulang tiap dibaca. Materialized view nyimpen hasilnya ke disk. View selalu fresh tapi lambat kalau querynya berat. Materialized view cepat tapi datanya sesuai REFRESH terakhir.
PostgreSQL, Oracle, dan SQL Server (namanya indexed view). BigQuery dan Snowflake juga punya dengan refresh otomatis. MySQL gak punya bawaan, jadi orang bikin tabel ringkasan manual plus scheduled job.
Tergantung seberapa basi data yang masih bisa diterima. Dashboard harian cukup tiap jam. Laporan bulanan cukup sekali sehari. Jangan refresh tiap menit kalau yang buka cuma 5 orang per hari.
Dia makan storage, dan proses REFRESH-nya berat karena ngejalanin query aslinya dari awal. Jadwalkan refresh bergiliran dan hapus yang udah gak dipakai.
Kalau datanya harus real-time kayak stok gudang. Juga kalau querynya udah di bawah 300 milidetik, nambah materialized view cuma nambah maintenance.
Tiga hal yang perlu kamu ingat. Materialized view mindahin kerjaan berat dari jam sibuk ke jam sepi, bukan ngilangin kerjaannya. Unique index itu wajib kalau kamu mau refresh tanpa ngunci pembaca. Dan data basi itu harga yang harus kamu bayar, jadi pastiin bisnisnya sanggup nerima.
Cek query paling lambat di dashboard kamu sekarang. Kalau dia dibaca puluhan kali sehari dan datanya jarang berubah, itu kandidat pertama.
Kalau kamu masih ngerasa query-nya lambat bahkan setelah pakai materialized view, biasanya masalahnya di index. Latihan bikin dan baca materialized view dari data asli bisa kamu coba langsung di NgulikSQL tanpa install database.
Lanjut baca stored procedure SQL kalau kamu mau otomatisin proses refresh-nya sekalian.
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.