Belajar Apache Spark - Advanced SQL & Analytics
Episode 15 of 23

Belajar Apache Spark - Advanced SQL & Analytics

Episode ini membahas analitik SQL tingkat lanjut: CTE, subqueries, dan nested queries, user-defined functions dan aggregate functions, integrasi spatial dan graph processing, serta integrasi dengan Delta Lake dan Iceberg untuk lakehouse.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Pendahuluan

Kalian sudah menguasai SQL dasar: select, join, agregasi, dan window. Episode 15 ini menaikkan level: query yang kompleks, fungsi buatan sendiri, dan integrasi dengan sistem lakehouse modern. Ini adalah keterampilan yang memisahkan analis SQL biasa dari engineer analitik.

Di dunia nyata, query tidak pernah sesederhana buku latihan. Butuh CTE untuk membagi logika, subquery untuk filtering bertingkat, UDF untuk logika khusus domain, dan format tabel yang mendukung transaksi serta time travel. Semuanya ada di Spark.

Episode ini membahas empat topik: CTE dan nested queries, UDF dan UDAF, spatial dan graph analytics, serta integrasi dengan Delta Lake dan Iceberg.

CTE, Subqueries, dan Nested Queries

CTE untuk Query Bertingkat

CTE (Common Table Expression) membagi query besar menjadi blok bernama yang bisa dipakai ulang. Ini membuat logika rumit mudah dibaca dan di-debug:

CTE berantai di Spark SQL
WITH transaksi_valid AS (
    SELECT * FROM transaksi WHERE status = 'selesai'
),
per_kota AS (
    SELECT kota, SUM(jumlah) AS total
    FROM transaksi_valid
    GROUP BY kota
)
SELECT kota, total, RANK() OVER (ORDER BY total DESC) AS peringkat
FROM per_kota;

WITH transaksi_valid AS (...) mendefinisikan CTE pertama yang dipakai CTE kedua. Spark mengevaluasi CTE secara efisien dan bisa menghindari pembacaan ulang jika hasilnya dipakai beberapa kali.

Subqueries dan Nested Queries

Spark SQL mendukung correlated subquery — subquery yang merujuk kolom dari query luar:

Subquery terkorelasi
SELECT nama, jumlah
FROM transaksi t
WHERE jumlah > (
    SELECT AVG(jumlah)
    FROM transaksi
    WHERE kota = t.kota
);

Subquery di atas membandingkan setiap transaksi dengan rata-rata di kotanya sendiri. Spark menangani ini dengan window dan join secara otomatis — namun untuk data sangat besar, subquery terkorelasi bisa mahal dan sering lebih baik ditulis ulang sebagai window function atau self join.

UDF dan UDAF

UDF di Spark SQL

Logika yang tidak tersedia di fungsi bawaan bisa dibuat sebagai UDF (User-Defined Function). Contoh sederhana dengan PySpark:

PythonMendaftarkan UDF
from pyspark.sql import functions as F
 
def kategori_stok(stok):
    if stok == 0:
        return "habis"
    if stok < 10:
        return "menipis"
    return "cukup"
 
spark.udf.register("kategori_stok", kategori_stok)

Lalu pakai di SQL: SELECT kategori_stok(stok) FROM produk. Catatan penting: UDF Python melewati Catalyst dan memaksa serialisasi, jadi untuk data besar pastikan UDF memang diperlukan — sering kali logika yang sama bisa ditulis dengan F.when.

UDAF untuk Agregasi Kustom

UDAF (User-Defined Aggregate Function) menggabungkan banyak baris menjadi satu nilai. Di Scala dan Java, implementasikan Aggregator dengan buffer yang bisa digabungkan secara paralel:

Struktur Aggregator
zero → merge(b, input) → merge(b1, b2) → finish(b)

UDAF bisa menggabungkan hasil antar partisi, sehingga agregasi tetap terdistribusi. Detail implementasinya dibahas lebih dalam di episode 17.

Spatial, Graph Processing, dan Advanced Windowing

Spatial Analytics dengan Sedona

Analisis spasial (jarak, bounding box, join berbasis geometri) tidak ada di inti Spark. Ekosistem menyediakan Sedona (sebelumnya GeoSpark) sebagai library pihak ketiga yang menambahkan tipe geometri dan fungsi spasial:

Fungsi spasial Sedona
ST_Distance, ST_Contains, ST_Intersects, ST_Buffer

Untuk kebutuhan ringan tanpa library, kombinasi F.atan2, F.sin, dan trigonometri lain bisa menghitung jarak haversine — namun untuk produksi, library spesialis jauh lebih andal.

Graph Processing dengan GraphX

GraphX adalah API graph Spark untuk analisis jaringan: mencari jalur terpendek, peringkat halaman (PageRank), dan komunitas. Cocok untuk rekomendasi sosial, deteksi fraud, dan analisis transportasi. Diperkenalkan di episode 21 sebagai bagian ekosistem library Spark.

Advanced Windowing

Gabungkan window dengan logika kompleks:

PythonWindow dengan rentang khusus
from pyspark.sql.window import Window
from pyspark.sql import functions as F
 
w = Window.partitionBy("kota") \
    .orderBy("tanggal") \
    .rowsBetween(Window.unboundedPreceding, Window.currentRow)
 
hasil = df.withColumn("total_kumulatif", F.sum("jumlah").over(w))

rowsBetween(Window.unboundedPreceding, Window.currentRow) menciptakan kumulatif running total per kota — pola dasar untuk metrik seperti revenue to-date.

Integrasi dengan Delta Lake dan Iceberg

Delta Lake

Delta Lake menambahkan lapisan transaksi ACID di atas Parquet: schema enforcement, time travel, dan merge (upsert) — kemampuan yang tidak dimiliki Parquet polos:

Merge dengan Delta
MERGE INTO transaksi_delta AS target
USING pembaruan AS source
ON target.id = source.id
WHEN MATCHED THEN UPDATE SET jumlah = source.jumlah
WHEN NOT MATCHED THEN INSERT *;

MERGE INTO ... USING ... melakukan upsert atomik — sangat berguna untuk pipeline CDC dan SCD (slowly changing dimensions). Time travel memungkinkan query ke versi data lama: SELECT * FROM t VERSION AS OF 10.

Apache Iceberg

Iceberg adalah alternatif open table format dengan fokus pada konsistensi snapshot, hidden partitioning, dan kemampuan scale besar:

Membuat tabel Iceberg
CREATE TABLE produk_iceberg (
  id INT, nama STRING, harga DECIMAL(10,2)
) USING iceberg
PARTITIONED BY (nama);

Perbedaan utama dengan Delta: Iceberg menyimpan daftar partisi secara eksplisit (hidden partitioning) sehingga query otomatis memakai pruning tanpa kalian menyebut kolom partisi. Baik Delta maupun Iceberg mengubah data lake menjadi lakehouse — data lake dengan sifat warehouse.

Tip

Pilih open table format lebih awal dalam arsitektur, bukan setelah data membesar. Migrasi Parquet polos ke Delta atau Iceberg membutuhkan rewrite data yang mahal. Keputusan ini akan dielaborasi di episode 21.

Penutup

Episode 15 memperluas perangkat analitik kalian: CTE dan subquery merapikan query kompleks, UDF dan UDAF menambahkan logika kustom, library spasial dan graph menangani domain khusus, serta Delta Lake dan Iceberg membawa transaksi dan time travel ke data lake.

Inti yang harus dibawa pulang:

  • CTE membagi query kompleks menjadi blok bernama yang dapat dibaca.
  • Subquery terkorelasi bisa diganti window function untuk efisiensi.
  • UDF Python melewati Catalyst — gunakan hanya saat diperlukan.
  • Delta memberi ACID, time travel, dan merge; Iceberg memberi hidden partitioning.
  • Open table format sebaiknya dipilih di awal arsitektur data.

Di episode 16 selanjutnya kita akan membahas save and restore, checkpointing, dan fault tolerance — checkpointing di Structured Streaming, perilaku recovery saat kegagalan, state management untuk streaming jobs, serta best practices untuk aplikasi streaming jangka panjang.

Belajar Apache Spark - Advanced SQL & Analytics | Belajar Apache Spark