Delta Lake vs Apache Iceberg 2026: Arsitektur Lakehouse dan Pertanyaan Interview

Panduan lengkap perbandingan Delta Lake dan Apache Iceberg untuk arsitektur lakehouse. Termasuk contoh kode, praktik terbaik, dan pertanyaan interview data engineering 2026.

Delta Lake vs Apache Iceberg 2026: Arsitektur Lakehouse dan Pertanyaan Interview

Arsitektur data lakehouse telah menjadi standar industri untuk platform data modern pada tahun 2026. Di jantung transformasi ini terdapat dua format tabel terbuka yang dominan: Delta Lake dan Apache Iceberg. Kedua teknologi ini memungkinkan organisasi menggabungkan keunggulan data lake (penyimpanan murah, format terbuka, skalabilitas) dengan kemampuan data warehouse (transaksi ACID, schema evolution, time travel). Artikel ini membahas secara mendalam perbandingan Delta Lake dan Apache Iceberg, implementasi praktis, serta pertanyaan interview yang sering muncul dalam wawancara data engineering.

Apa itu Format Tabel Lakehouse?

Format tabel lakehouse adalah lapisan metadata yang berada di atas file data (Parquet, ORC) di object storage seperti S3, GCS, atau Azure Blob. Format ini menyediakan fitur seperti transaksi ACID, schema enforcement, dan versioning tanpa memerlukan database tradisional. Delta Lake dikembangkan oleh Databricks, sementara Apache Iceberg dibuat oleh Netflix dan kini menjadi proyek Apache top-level. Keduanya mendukung multiple compute engines dan menjadi fondasi arsitektur lakehouse modern.

Arsitektur Delta Lake: Struktur dan Komponen Utama

Delta Lake menggunakan transaction log berbasis JSON yang disebut _delta_log untuk melacak semua perubahan pada tabel. Setiap operasi write menghasilkan file JSON baru yang mencatat file mana yang ditambahkan atau dihapus. Pendekatan ini memungkinkan ACID transactions dan concurrent reads/writes yang aman.

Struktur direktori Delta Lake terlihat seperti berikut:

text
my_delta_table/
├── _delta_log/
│   ├── 00000000000000000000.json
│   ├── 00000000000000000001.json
│   ├── 00000000000000000002.json
│   └── 00000000000000000010.checkpoint.parquet
├── part-00000-xxx.parquet
├── part-00001-xxx.parquet
└── part-00002-xxx.parquet

Membuat dan menulis ke Delta table menggunakan PySpark:

python
from delta import DeltaTable
from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .appName("DeltaLakeDemo") \
    .config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \
    .config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \
    .getOrCreate()

# Create Delta table with schema
df = spark.createDataFrame([
    (1, "Alice", "2026-01-15", 50000.00),
    (2, "Bob", "2026-01-16", 75000.00),
    (3, "Charlie", "2026-01-17", 60000.00)
], ["customer_id", "name", "signup_date", "revenue"])

df.write.format("delta").mode("overwrite").save("/data/customers_delta")

Delta Lake menyediakan fitur MERGE yang powerful untuk upsert operations:

python
from delta.tables import DeltaTable

# Load existing Delta table
delta_table = DeltaTable.forPath(spark, "/data/customers_delta")

# New data to merge
updates_df = spark.createDataFrame([
    (2, "Bob Smith", "2026-01-16", 80000.00),  # Update existing
    (4, "Diana", "2026-01-18", 45000.00)        # Insert new
], ["customer_id", "name", "signup_date", "revenue"])

# Perform MERGE operation
delta_table.alias("target").merge(
    updates_df.alias("source"),
    "target.customer_id = source.customer_id"
).whenMatchedUpdate(set={
    "name": "source.name",
    "revenue": "source.revenue"
}).whenNotMatchedInsert(values={
    "customer_id": "source.customer_id",
    "name": "source.name",
    "signup_date": "source.signup_date",
    "revenue": "source.revenue"
}).execute()

Apache Iceberg: Arsitektur dan Keunggulan

Apache Iceberg menggunakan pendekatan berbeda dengan menyimpan metadata dalam bentuk hierarki tiga tingkat: metadata files, manifest lists, dan manifest files. Arsitektur ini memungkinkan snapshot isolation yang lebih efisien dan partition evolution tanpa rewrite data.

Struktur metadata Iceberg:

text
warehouse/
└── my_iceberg_table/
    ├── metadata/
    │   ├── v1.metadata.json
    │   ├── v2.metadata.json
    │   ├── snap-xxx-1.avro (manifest list)
    │   └── xxx-m0.avro (manifest file)
    └── data/
        ├── partition=2026-01/
        │   ├── 00000-0-xxx.parquet
        │   └── 00001-0-xxx.parquet
        └── partition=2026-02/
            └── 00000-0-xxx.parquet

Membuat dan mengoperasikan Iceberg table:

python
from pyspark.sql import SparkSession

spark = SparkSession.builder \
    .appName("IcebergDemo") \
    .config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions") \
    .config("spark.sql.catalog.local", "org.apache.iceberg.spark.SparkCatalog") \
    .config("spark.sql.catalog.local.type", "hadoop") \
    .config("spark.sql.catalog.local.warehouse", "/warehouse") \
    .getOrCreate()

# Create Iceberg table with partitioning
spark.sql("""
    CREATE TABLE local.db.events (
        event_id BIGINT,
        event_type STRING,
        user_id BIGINT,
        event_timestamp TIMESTAMP,
        properties MAP<STRING, STRING>
    )
    USING iceberg
    PARTITIONED BY (days(event_timestamp))
""")

# Insert data
spark.sql("""
    INSERT INTO local.db.events VALUES
    (1, 'page_view', 100, timestamp '2026-01-15 10:30:00', map('page', '/home')),
    (2, 'click', 100, timestamp '2026-01-15 10:31:00', map('button', 'signup')),
    (3, 'purchase', 101, timestamp '2026-01-15 11:00:00', map('amount', '99.99'))
""")

Salah satu keunggulan utama Iceberg adalah hidden partitioning yang memisahkan partition scheme dari query:

python
# Partition evolution - change partitioning without rewriting data
spark.sql("""
    ALTER TABLE local.db.events
    ADD PARTITION FIELD hours(event_timestamp)
""")

# Query automatically uses optimal partition pruning
# Users don't need to know the partition structure
result = spark.sql("""
    SELECT event_type, count(*) as event_count
    FROM local.db.events
    WHERE event_timestamp >= '2026-01-15'
      AND event_timestamp < '2026-01-16'
    GROUP BY event_type
""")

Perbandingan Fitur: Delta Lake vs Apache Iceberg

Berikut perbandingan komprehensif antara Delta Lake dan Apache Iceberg berdasarkan fitur-fitur utama:

| Fitur | Delta Lake | Apache Iceberg | |-------|------------|----------------| | Transaction Log | JSON files dengan checkpoint | Hierarki metadata multi-level | | Schema Evolution | Add/rename columns | Full evolution termasuk reorder | | Partition Evolution | Memerlukan rewrite | In-place tanpa rewrite | | Time Travel | Berdasarkan version/timestamp | Snapshot-based dengan retention | | Compute Engine Support | Optimal di Spark/Databricks | Multi-engine (Spark, Flink, Trino, Presto) | | Catalog Integration | Unity Catalog, Hive | REST, Hive, AWS Glue, Nessie | | Delete Operations | Copy-on-write, merge-on-read | Copy-on-write, merge-on-read | | Community | Databricks-led | Apache Foundation, multi-vendor |

Time travel untuk audit dan debugging:

python
# Delta Lake time travel
df_v1 = spark.read.format("delta").option("versionAsOf", 1).load("/data/customers_delta")
df_timestamp = spark.read.format("delta").option("timestampAsOf", "2026-01-15 10:00:00").load("/data/customers_delta")

# Iceberg time travel
spark.sql("SELECT * FROM local.db.events VERSION AS OF 1")
spark.sql("SELECT * FROM local.db.events TIMESTAMP AS OF '2026-01-15 10:00:00'")

# Iceberg snapshot history
spark.sql("SELECT * FROM local.db.events.history").show()

Siap menguasai wawancara Data Engineering Anda?

Berlatih dengan simulator interaktif, flashcards, dan tes teknis kami.

Optimasi Performa dan Maintenance

Kedua format memerlukan maintenance rutin untuk performa optimal. Delta Lake menggunakan OPTIMIZE dan VACUUM, sementara Iceberg menggunakan compaction dan expire snapshots.

Optimasi Delta Lake:

python
from delta.tables import DeltaTable

delta_table = DeltaTable.forPath(spark, "/data/customers_delta")

# Compact small files into larger ones
delta_table.optimize().executeCompaction()

# Z-order for query optimization on specific columns
delta_table.optimize().executeZOrderBy("signup_date", "customer_id")

# Remove old versions (retain 7 days)
spark.sql("VACUUM '/data/customers_delta' RETAIN 168 HOURS")

# View table history
delta_table.history().show()

Optimasi Apache Iceberg:

python
# Compact data files
spark.sql("""
    CALL local.system.rewrite_data_files(
        table => 'db.events',
        strategy => 'binpack',
        options => map('target-file-size-bytes', '134217728')
    )
""")

# Sort data for better query performance
spark.sql("""
    CALL local.system.rewrite_data_files(
        table => 'db.events',
        strategy => 'sort',
        sort_order => 'event_timestamp ASC, event_type ASC'
    )
""")

# Expire old snapshots
spark.sql("""
    CALL local.system.expire_snapshots(
        table => 'db.events',
        older_than => TIMESTAMP '2026-01-08 00:00:00',
        retain_last => 5
    )
""")

# Remove orphan files
spark.sql("""
    CALL local.system.remove_orphan_files(
        table => 'db.events',
        older_than => TIMESTAMP '2026-01-01 00:00:00'
    )
""")

Integrasi dengan Data Pipeline Modern

Kedua format terintegrasi dengan baik dalam ekosistem data modern. Berikut contoh pipeline dengan Apache Airflow:

python
from airflow import DAG
from airflow.providers.apache.spark.operators.spark_submit import SparkSubmitOperator
from datetime import datetime, timedelta

default_args = {
    'owner': 'data-engineering',
    'depends_on_past': False,
    'email_on_failure': True,
    'retries': 2,
    'retry_delay': timedelta(minutes=5)
}

with DAG(
    'lakehouse_etl_pipeline',
    default_args=default_args,
    schedule_interval='@hourly',
    start_date=datetime(2026, 1, 1),
    catchup=False
) as dag:

    ingest_to_bronze = SparkSubmitOperator(
        task_id='ingest_raw_events',
        application='/jobs/ingest_events.py',
        conf={
            'spark.sql.extensions': 'io.delta.sql.DeltaSparkSessionExtension',
            'spark.jars.packages': 'io.delta:delta-spark_2.12:3.1.0'
        }
    )

    transform_to_silver = SparkSubmitOperator(
        task_id='transform_events',
        application='/jobs/transform_silver.py'
    )

    aggregate_to_gold = SparkSubmitOperator(
        task_id='aggregate_metrics',
        application='/jobs/aggregate_gold.py'
    )

    optimize_tables = SparkSubmitOperator(
        task_id='optimize_delta_tables',
        application='/jobs/optimize_maintenance.py'
    )

    ingest_to_bronze >> transform_to_silver >> aggregate_to_gold >> optimize_tables

Pertanyaan Interview Data Engineering: Lakehouse Architecture

Berikut pertanyaan interview yang sering muncul terkait Delta Lake dan Apache Iceberg pada tahun 2026:

Q1: Jelaskan perbedaan utama antara transaction log Delta Lake dan metadata architecture Apache Iceberg. Mana yang lebih baik untuk kasus penggunaan tertentu?

Delta Lake menggunakan transaction log berbasis JSON yang sequential, di mana setiap operasi menghasilkan file JSON baru. Checkpoint files dalam format Parquet dibuat secara berkala untuk mempercepat pembacaan state terbaru. Pendekatan ini sederhana dan efektif, tetapi memerlukan pembacaan banyak file JSON untuk merekonstruksi state pada cluster besar.

Apache Iceberg menggunakan hierarki metadata tiga tingkat: metadata files (JSON) yang menunjuk ke manifest lists (Avro), yang kemudian menunjuk ke manifest files (Avro) berisi informasi file data. Arsitektur ini memungkinkan pruning yang lebih efisien karena statistics disimpan di level manifest, dan snapshot isolation yang lebih baik untuk concurrent queries.

Delta Lake lebih cocok untuk tim yang sudah menggunakan Databricks ecosystem, memerlukan integrasi tight dengan Spark, dan menginginkan setup yang lebih sederhana. Iceberg lebih unggul untuk multi-engine environments (Spark, Flink, Trino), memerlukan partition evolution tanpa data rewrite, atau bekerja dengan catalogs seperti AWS Glue atau Apache Nessie.

Q2: Bagaimana partition evolution bekerja di Apache Iceberg? Mengapa ini menjadi keunggulan signifikan dibanding pendekatan tradisional?

Partition evolution di Iceberg memungkinkan perubahan skema partisi tanpa perlu menulis ulang data yang sudah ada. Ketika partition scheme berubah, Iceberg menyimpan informasi ini di metadata dan secara otomatis menangani query yang mencakup data dengan partisi lama dan baru.

Contohnya, jika tabel awalnya dipartisi berdasarkan bulan (month(event_date)) dan kemudian diubah ke hari (day(event_date)), data lama tetap dalam partisi bulanan sementara data baru ditulis ke partisi harian. Query planner Iceberg secara otomatis menerapkan partition pruning yang tepat untuk kedua jenis partisi.

Ini berbeda signifikan dari pendekatan Hive tradisional atau bahkan Delta Lake, di mana perubahan partisi memerlukan rewriting seluruh tabel. Untuk tabel petabyte-scale, ini menghemat waktu dan biaya komputasi yang substansial.

Q3: Apa itu copy-on-write vs merge-on-read? Kapan menggunakan masing-masing strategi?

Copy-on-write (COW) menulis ulang seluruh file data ketika ada update atau delete. Pendekatan ini menghasilkan read performance yang optimal karena tidak ada overhead saat query, tetapi write performance bisa lambat untuk updates yang sering.

Merge-on-read (MOR) menyimpan deletes dan updates dalam file terpisah (delete files) dan menggabungkannya saat read time. Write performance lebih cepat, tetapi reads memerlukan overhead untuk merging.

Gunakan copy-on-write untuk: workloads dengan lebih banyak reads daripada writes, batch processing dengan window update yang jelas, dan kasus di mana read latency kritikal.

Gunakan merge-on-read untuk: streaming ingestion dengan frequent updates, workloads dengan high write throughput, dan kasus di mana write latency lebih penting daripada read latency. Dalam praktik, banyak tim mengkombinasikan keduanya dengan compaction job yang mengkonversi MOR files ke COW secara berkala.

Q4: Bagaimana implementasi data quality checks dalam lakehouse architecture?

Data quality dalam lakehouse architecture diimplementasikan di beberapa layer:

Pada ingestion layer, gunakan schema enforcement yang disediakan oleh Delta Lake atau Iceberg untuk menolak data yang tidak sesuai schema. Delta Lake menyediakan constraint seperti CHECK constraints dan NOT NULL.

Pada transformation layer, tools seperti Great Expectations atau dbt tests dapat diintegrasikan untuk validasi data. Contohnya, validasi bahwa tidak ada nilai null di kolom kritikal, nilai berada dalam range yang diharapkan, atau referential integrity terjaga.

Pada serving layer, implementasikan monitoring untuk data freshness dan completeness. Alert ketika tabel tidak diupdate dalam window yang diharapkan atau ketika row counts berubah secara anomali.

Q5: Jelaskan strategi untuk migrasi dari Hive tables ke format lakehouse (Delta/Iceberg).

Migrasi dari Hive ke format lakehouse dapat dilakukan dengan beberapa pendekatan:

In-place conversion untuk Iceberg: menggunakan procedure migrate yang menambahkan metadata Iceberg ke existing Parquet files tanpa data movement. Ini memungkinkan quick migration tetapi tidak memberikan benefit file optimization.

CTAS (Create Table As Select) migration: membuat tabel baru dalam format target dan menyalin data. Pendekatan ini memungkinkan optimasi seperti re-partitioning dan file sizing, tetapi memerlukan storage tambahan dan downtime.

Dual-write migration: menulis ke kedua format selama periode transisi, memvalidasi consistency, lalu cutover ke format baru. Ini minimizes risk tetapi memerlukan effort engineering lebih besar.

Delta Lake juga menyediakan CONVERT TO DELTA untuk konversi Parquet tables yang sudah ada. Best practice adalah memulai dengan tabel yang kurang kritikal, validasi thoroughly, lalu migrasikan tabel penting secara bertahap.

Best Practices untuk Production Lakehouse

Mengelola lakehouse di production memerlukan perhatian pada beberapa aspek penting:

python
# Example: Production-ready table configuration for Delta Lake
spark.sql("""
    CREATE TABLE IF NOT EXISTS prod.analytics.user_events (
        event_id STRING NOT NULL,
        user_id BIGINT NOT NULL,
        event_type STRING NOT NULL,
        event_properties MAP<STRING, STRING>,
        event_timestamp TIMESTAMP NOT NULL,
        processing_timestamp TIMESTAMP NOT NULL,
        _partition_date DATE GENERATED ALWAYS AS (CAST(event_timestamp AS DATE))
    )
    USING DELTA
    PARTITIONED BY (_partition_date)
    TBLPROPERTIES (
        'delta.autoOptimize.optimizeWrite' = 'true',
        'delta.autoOptimize.autoCompact' = 'true',
        'delta.logRetentionDuration' = 'interval 30 days',
        'delta.deletedFileRetentionDuration' = 'interval 7 days',
        'delta.columnMapping.mode' = 'name'
    )
""")

# Example: Production-ready table configuration for Iceberg
spark.sql("""
    CREATE TABLE IF NOT EXISTS local.analytics.user_events (
        event_id STRING NOT NULL,
        user_id BIGINT NOT NULL,
        event_type STRING NOT NULL,
        event_properties MAP<STRING, STRING>,
        event_timestamp TIMESTAMP NOT NULL,
        processing_timestamp TIMESTAMP NOT NULL
    )
    USING ICEBERG
    PARTITIONED BY (days(event_timestamp))
    TBLPROPERTIES (
        'write.format.default' = 'parquet',
        'write.parquet.compression-codec' = 'zstd',
        'write.target-file-size-bytes' = '134217728',
        'history.expire.max-snapshot-age-ms' = '604800000',
        'write.metadata.delete-after-commit.enabled' = 'true'
    )
""")

Monitoring dan observability sangat penting untuk lakehouse production. Implementasikan metrics untuk: jumlah file per partisi (untuk mendeteksi small files problem), latency operasi write dan read, storage utilization dan growth rate, serta query performance patterns.

Mulai berlatih!

Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.

Kesimpulan: Memilih Format yang Tepat

Delta Lake dan Apache Iceberg keduanya merupakan solusi mature untuk arsitektur lakehouse pada tahun 2026. Pemilihan antara keduanya bergantung pada beberapa faktor:

Pilih Delta Lake jika: organisasi sudah menggunakan Databricks sebagai platform utama, tim memerlukan integrasi tight dengan Spark ecosystem, atau membutuhkan fitur seperti Change Data Feed untuk streaming CDC.

Pilih Apache Iceberg jika: memerlukan interoperabilitas multi-engine (Spark, Flink, Trino, Presto), partition evolution tanpa data rewrite adalah kebutuhan kritikal, atau preferensi untuk standar terbuka dengan governance Apache Foundation.

Dalam praktik, banyak organisasi mengadopsi kedua format untuk use cases yang berbeda. Yang terpenting adalah memahami trade-offs masing-masing dan memilih berdasarkan kebutuhan spesifik workload.

Poin-poin utama untuk diingat:

  • Transaction log vs metadata hierarchy: Delta Lake menggunakan JSON logs, Iceberg menggunakan multi-level metadata
  • Partition evolution: Iceberg unggul dengan in-place evolution tanpa data rewrite
  • Engine support: Delta Lake optimal di Spark, Iceberg mendukung multi-engine
  • Maintenance: Kedua format memerlukan compaction dan cleanup rutin
  • Interview preparation: Pahami arsitektur internal, bukan hanya syntax API

Menguasai kedua teknologi ini memberikan fleksibilitas dalam menghadapi berbagai tantangan data engineering dan mempersiapkan kandidat untuk pertanyaan interview yang semakin mendalam tentang arsitektur lakehouse modern.

Mulai berlatih!

Uji pengetahuan Anda dengan simulator wawancara dan tes teknis kami.

Bagikan

Artikel terkait