OLTP vs OLAP

Perbedaan desain basis data transaksional dan analitis, dari pola akses sampai bentuk skemanya.

Daftar isi

Topik ini membandingkan dua pola desain basis data yang mendasari pekerjaan data engineering, yaitu OLTP untuk beban transaksional dan OLAP untuk beban analitik. Perbandingannya mencakup pola akses, ukuran transaksi, bentuk skema, dan tingkat normalisasi. Satu demonstrasi di bagian akhir menjalankan pertanyaan yang sama atas skema perpustakaan tertenormalisasi dan tabel analitik denormalisasi, sehingga perbedaan kedua pola terlihat pada keluaran nyata, bukan sekadar pada definisi.

Dua beban kerja yang berbeda#

OLTP (Online Transaction Processing) adalah pola desain basis data yang dioptimalkan untuk banyak transaksi kecil, yaitu operasi baca dan tulis sempit yang datang terus-menerus dari aplikasi, misalnya mencatat satu peminjaman buku atau memperbarui stok satu judul. Setiap transaksi menyentuh sedikit baris dan harus selesai dalam hitungan milidetik, sehingga indeks disetel untuk kecepatan transaksi dan konsistensi dijaga dengan ketat. Reis dan Housley dalam Fundamentals of Data Engineering menegaskan bahwa sistem seperti ini dibangun untuk kebutuhan operasionalnya sendiri, dan analitik bukan tujuan desainnya.

OLAP (Online Analytical Processing) adalah pola desain yang dioptimalkan untuk kueri pembacaan besar, yaitu menyapu banyak baris, mengagregasi, dan mengelompokkan dalam sekali jalan. Penggunanya bukan aplikasi yang sedang bertransaksi, melainkan analis, dasbor, dan pipeline yang menyiapkan data untuk analisis. Kueri semacam ini menghitung ringkasan seperti jumlah peminjaman per judul sepanjang tahun, pekerjaan yang jarang dilakukan sistem operasional.

Kedua beban kerja menuntut sifat fisik penyimpanan yang berbeda, sehingga satu basis data sulit menjadi optimal pada keduanya. Kueri analitik yang berat dijalankan pada basis data OLTP produksi dapat menunda transaksi pengguna, sedangkan skema transaksional yang dipertahankan di sisi analitik membuat setiap kueri harus menyusun ulang detail dari banyak tabel. Ketegangan inilah yang melahirkan dua bentuk desain yang berbeda arah.

Perbandingan sisi demi sisi#

Perbedaan OLTP dan OLAP paling mudah dibaca dari empat aspek yang saling terkait, yaitu pola akses, ukuran transaksi, bentuk skema, dan normalisasi. Tabel berikut merangkum aspek-aspek tersebut beserta beberapa konsekuensinya.

AspekOLTPOLAP
Pola aksesbaca-tulis kecil berulang, satu baris atau sedikit baris per operasibaca besar: menyapu banyak baris, agregasi, pengelompokan
Ukuran transaksikecil dan cepat, hitungan milidetikberat dan panjang, hitungan detik hingga menit
Bentuk skemabanyak tabel kecil yang terhubung kuncitabel lebar (wide table) atau star schema
Normalisasitinggi, umumnya hingga bentuk normal ketiga (3NF)rendah, redundansi disengaja demi kecepatan pembacaan
Prioritaskonsistensi dan kecepatan transaksikecepatan agregasi dan kemudahan analisis
Contoh operasicatat satu peminjaman bukujumlah peminjaman per judul sepanjang tahun

Normalisasi tinggi pada sisi OLTP wajar karena setiap fakta disimpan satu kali, sehingga pembaruan tidak mudah bertentangan. Konsekuensinya, kueri analitik harus menempuh banyak join untuk menyusun ulang konteks, dan biaya itu membengkak saat data membesar. Sisi OLAP membalik keputusan tersebut dengan menerima redundansi secara terkendali. Bentuk akhirnya beragam, mulai dari tabel lebar hingga star schema, yaitu skema yang menempatkan satu tabel fakta di tengah dan tabel dimensi di sekelilingnya, sehingga agregasi cukup membaca satu tabel atau sedikit tabel.

Demonstrasi: pertanyaan yang sama pada dua bentuk skema#

Skema OLTP pada demonstrasi ini memakai ranah perpustakaan berisi tiga tabel tertenormalisasi, yaitu anggota, buku, dan peminjaman. Skripnya dibangun di atas DuckDB, yaitu mesin basis data analitik yang berjalan tertanam tanpa server. Skrip itu melakukan tiga hal: menjalankan kueri khas OLTP yang menyusun ulang detail peminjaman, membuat tabel analitik denormalisasi dari skema tersebut, dan menjawab pertanyaan agregasi tanpa satu pun join.

python demo-oltp-olap.py
"""Membandingkan kueri pada skema OLTP tertenormalisasi dengan tabel analitik denormalisasi."""

import duckdb

con = duckdb.connect(":memory:")

# Sisi OLTP: tiga tabel tertenormalisasi perpustakaan
con.execute("CREATE TABLE anggota (id_anggota INTEGER PRIMARY KEY, nama VARCHAR NOT NULL)")
con.execute("CREATE TABLE buku (id_buku INTEGER PRIMARY KEY, judul VARCHAR NOT NULL)")
con.execute("""
    CREATE TABLE peminjaman (
        id_pinjam  INTEGER PRIMARY KEY,
        id_anggota INTEGER NOT NULL REFERENCES anggota(id_anggota),
        id_buku    INTEGER NOT NULL REFERENCES buku(id_buku),
        tanggal    DATE    NOT NULL
    )
""")
con.executemany("INSERT INTO anggota VALUES (?, ?)", [(1, "Ali"), (2, "Budi"), (3, "Citra")])
con.executemany("INSERT INTO buku VALUES (?, ?)", [
    (10, "Matematika untuk SMA"),
    (11, "Fisika Dasar"),
    (12, "Kamus Bahasa Indonesia"),
])
con.executemany("INSERT INTO peminjaman VALUES (?, ?, ?, ?)", [
    (1, 1, 10, "2026-02-02"),
    (2, 2, 10, "2026-02-03"),
    (3, 1, 11, "2026-02-04"),
    (4, 3, 11, "2026-02-05"),
    (5, 3, 10, "2026-02-06"),
])

# Kueri khas OLTP: satu pertanyaan sempit, dua join untuk menyusun ulang detail
print("Sisi OLTP: riwayat peminjaman Ali, dua join ke tabel anggota dan buku")
rows = con.execute("""
    SELECT p.id_pinjam, b.judul, p.tanggal
    FROM peminjaman p
    JOIN anggota a ON a.id_anggota = p.id_anggota
    JOIN buku b    ON b.id_buku    = p.id_buku
    WHERE a.nama = 'Ali'
    ORDER BY p.id_pinjam
""").fetchall()
for id_pinjam, judul, tanggal in rows:
    print(f"  pinjam #{id_pinjam}  {judul:<24} {tanggal}")

# Sisi OLAP: satu tabel denormalisasi, dibangun sekali lalu dikueri tanpa join
con.execute("""
    CREATE TABLE peminjaman_analitik AS
    SELECT p.id_pinjam, a.nama AS nama_anggota, b.judul AS judul_buku, p.tanggal
    FROM peminjaman p
    JOIN anggota a ON a.id_anggota = p.id_anggota
    JOIN buku b    ON b.id_buku    = p.id_buku
""")
kolom = [d[0] for d in con.execute("SELECT * FROM peminjaman_analitik LIMIT 0").description]
print("Sisi OLAP: peminjaman_analitik menyatukan kolom", ", ".join(kolom))

print("Sisi OLAP: jumlah peminjaman per judul, satu tabel tanpa join")
rows = con.execute("""
    SELECT judul_buku, COUNT(*) AS jumlah
    FROM peminjaman_analitik
    GROUP BY judul_buku
    ORDER BY judul_buku
""").fetchall()
for judul, jumlah in rows:
    print(f"  {judul:<24} {jumlah}")
text Keluaran
Sisi OLTP: riwayat peminjaman Ali, dua join ke tabel anggota dan buku
  pinjam #1  Matematika untuk SMA     2026-02-02
  pinjam #3  Fisika Dasar             2026-02-04
Sisi OLAP: peminjaman_analitik menyatukan kolom id_pinjam, nama_anggota, judul_buku, tanggal
Sisi OLAP: jumlah peminjaman per judul, satu tabel tanpa join
  Fisika Dasar             2
  Matematika untuk SMA     3

Keluarannya memperlihatkan dua jalur menuju jawaban yang sama. Jalur OLTP memerlukan dua join karena informasi peminjaman tersebar di tiga tabel, bentuk yang tepat untuk menjaga setiap fakta tersimpan satu kali. Jalur OLAP menggabungkan ketiganya sekali saja menjadi tabel lebar, kemudian kueri agregasi berikutnya cukup membaca satu tabel. Pola ini berlaku umum di pipeline: pembentukan skema analitik dikerjakan satu kali oleh transformasi, sedangkan banyak kueri analitik menikmati hasilnya berulang kali.

Konsekuensi bagi pipeline data#

Perbedaan kedua pola menentukan arsitektur pipeline. Data diekstrak dari basis data OLTP tanpa mengganggu transaksi produksi, lalu dimuat ke penyimpanan analitik yang skemanya dibentuk ulang secara sadar, baik sebagai tabel lebar, star schema, maupun berkas kolom terbuka. Pemisahan ini juga memberi ruang memilih mesin yang tepat untuk tiap sisi, karena basis data transaksional dan analitik jarang unggul pada keduanya sekaligus. Basis data OLTP tetap mempertahankan bentuk tertenormalisasinya karena bentuk itu memang yang dibutuhkan aplikasi.

Keputusan tentang bentuk skema analitik juga menentukan biaya. Skema yang tepat memangkas jumlah join, menyederhanakan kueri konsumen, dan membuat model mudah dipelihara, sedangkan skema yang menyalin struktur operasional apa adanya memindahkan kerumitan ke setiap kueri. Karena itu pemodelan data analitik selalu berangkat dari beban kerja pembacanya dan bukan dari struktur sistem sumbernya. Bentuk akhir tabel ditentukan oleh pertanyaan yang akan dijawab, sedangkan struktur sumber hanya menentukan titik berangkatnya.

Kesalahan umum#

Tiga kesalahan berikut paling sering muncul ketika kedua pola desain ini baru dipisahkan.

  1. Menjalankan kueri agregasi berat langsung pada basis data OLTP produksi. Penyebabnya, kueri analitik menyita sumber daya yang dibutuhkan transaksi pengguna sehingga aplikasi melambat. Perbaikannya, ekstrak data ke salinan analitik terpisah dan jalankan kueri di sana.
  2. Menyalin skema OLTP apa adanya ke penyimpanan analitik. Penyebabnya, struktur tertenormalisasi memaksa setiap kueri analitik menempuh banyak join dan konsumen data kesulitan memahaminya. Perbaikannya, bentuk ulang skema menjadi tabel lebar atau star schema sesuai kebutuhan analisis.
  3. Menghapus seluruh redundansi di sisi analitik karena terbiasa dengan normalisasi. Penyebabnya, kebiasaan OLTP memandang redundansi sebagai cacat, padahal redundansi terkendali justru mempercepat agregasi. Perbaikannya, terima redundansi yang dijaga pipeline dan catat asalnya secara jelas.

Ringkasan#

  • OLTP melayani transaksi kecil dan cepat untuk aplikasi, sedangkan OLAP melayani kueri pembacaan besar untuk analisis.
  • Skema OLTP tertenormalisasi hingga 3NF demi konsistensi penulisan, sedangkan skema analitik denormalisasi demi kecepatan pembacaan.
  • Pipeline memindahkan data dari sisi OLTP ke sisi OLAP dan membentuk skema analitik satu kali agar banyak kueri menikmatinya.
  • Pertanyaan yang sama dapat dijawab dari kedua bentuk skema, tetapi biaya join dan pola kuerinya berbeda, sebagaimana ditunjukkan demonstrasinya.

Referensi#