Saat mengolah data untuk analisis, kamu biasanya dihadapkan pada dua pilihan: memakai library DataFrame seperti Pandas atau Polars, atau menyiapkan database server seperti PostgreSQL. DuckDB menawarkan jalan ketiga: sebuah database analitik (OLAP) embedded yang bisa kamu pakai langsung dari Python tanpa menginstal server apa pun, sekaligus sanggup memproses jutaan baris dengan sangat cepat berkat mesin columnar-nya. Di tutorial ini kita akan mempelajari DuckDB dari nol sampai bisa menganalisis data nyata.
Apa Itu DuckDB?
DuckDB adalah in-process analytical database yang populer disebut sebagai “SQLite untuk analitik”. Bedanya dengan SQLite: SQLite dirancang untuk transaksi (OLTP), sedangkan DuckDB dirancang untuk kueri analitik (OLAP) — agregasi, penggabungan, dan pemindaian kolom berukuran besar. Karena bersifat embedded, kamu tidak perlu menjalankan server terpisah; data tersimpan dalam satu file .duckdb atau bahkan hanya di memori.
DuckDB juga bisa membaca langsung file CSV, Parquet, JSON, hingga tabel SQLite tanpa perlu import manual. Ini menjadikannya alat favorit untuk data exploration dan pipeline ETL ringan.
Persiapan: Install DuckDB
Pastikan kamu sudah punya Python 3.8 ke atas (lihat panduan install Python jika belum). Lalu install paket duckdb lewat pip:
pip install duckdb
# atau dengan uv
uv add duckdb
Setelah terpasang, kita bisa langsung mencobanya. Paket ini tidak membutuhkan dependensi eksternal lain, jadi proses instalasinya cepat dan ringan.
Koneksi dan Query Dasar
DuckDB bisa dipakai lewat dua cara: koneksi eksplisit (mirip sqlite3) atau fungsi duckdb.sql() untuk satu baris kueri. Mari mulai dari koneksi in-memory:
import duckdb
# 1) Koneksi in-memory (hilang saat program selesai)
con = duckdb.connect()
# 2) Koneksi ke file persisten
# con = duckdb.connect("analitik.duckdb")
hasil = con.execute("SELECT 'Halo DuckDB!' AS pesan").fetchall()
print(hasil) # [('Halo DuckDB!',)]
Untuk kueri cepat tanpa objek koneksi, gunakan duckdb.sql() yang langsung mengembalikan hasil. Metode .df() mengubah hasil kueri menjadi DataFrame Pandas, sementara .fetchall() mengembalikan daftar tuple:
import duckdb
# Kueri sekali jalan, hasil langsung jadi DataFrame Pandas
df = duckdb.sql("SELECT 1 + 1 AS hasil, 'dua' AS kata").df()
print(df)
Query Langsung dari File CSV & Parquet
Fitur paling keren dari DuckDB adalah kemampuannya membaca file data secara langsung lewat SQL — tanpa perlu membuat tabel dulu. Coba buat file penjualan.csv berikut, lalu query langsung dari file tersebut:
cat > penjualan.csv <<'EOF'
id,produk,kategori,jumlah,harga
1,Laptop,Elektronik,5,12000000
2,Mouse,Elektronik,20,150000
3,Meja,Furnitur,3,800000
4,Keyboard,Elektronik,15,400000
5,Kursi,Furnitur,7,1500000
EOF
import duckdb
# Baca CSV langsung dari file, tanpa membuat tabel
hasil = duckdb.sql("""
SELECT kategori,
SUM(jumlah) AS total_terjual,
SUM(jumlah * harga) AS total_pendapatan
FROM 'penjualan.csv'
GROUP BY kategori
ORDER BY total_pendapatan DESC
""").df()
print(hasil)
DuckDB mendeteksi skema dan tipe kolom secara otomatis saat membaca CSV/Parquet. Untuk file Parquet, tinggal ganti 'penjualan.csv' menjadi 'data.parquet' — sintaksnya sama persis.
Integrasi dengan Pandas & Polars
DuckDB bisa membaca DataFrame yang sudah ada di memori dan menjalankan SQL di atasnya. Ini sangat berguna ketika kamu sudah punya data di Pandas atau Polars lalu ingin agregasi yang lebih ekspresif lewat SQL:
import pandas as pd
import duckdb
df = pd.DataFrame({
"nama": ["Andi", "Budi", "Citra", "Dewi"],
"usia": [25, 30, 22, 27],
"kota": ["Jakarta", "Bandung", "Jakarta", "Surabaya"]
})
con = duckdb.connect()
con.register("pengguna", df) # daftarkan DataFrame sebagai tabel 'pengguna'
hasil = con.execute("""
SELECT kota, COUNT(*) AS jumlah, AVG(usia) AS rata_rata_usia
FROM pengguna
GROUP BY kota
ORDER BY jumlah DESC
""").df()
print(hasil)
Hal yang sama juga berlaku untuk DataFrame Polars, sehingga kamu bisa memadukan kecepatan Polars dengan fleksibilitas SQL DuckDB:
import polars as pl
import duckdb
df = pl.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
con = duckdb.connect()
con.register("data_polars", df)
print(con.execute("SELECT a, b, a * b AS hasil_kali FROM data_polars").df())
Membuat Tabel dan Analisis Lebih Lanjut
Untuk data yang perlu disimpan permanen, gunakan koneksi file .duckdb. Kita bisa membuat tabel, mengisinya, lalu memakai window function untuk analisis peringkat:
import duckdb
con = duckdb.connect("analitik.duckdb") # file database persisten
con.execute("""
CREATE TABLE IF NOT EXISTS penjualan (
id INTEGER,
produk VARCHAR,
kategori VARCHAR,
jumlah INTEGER,
harga DECIMAL(12,2)
)
""")
con.execute("""
INSERT INTO penjualan VALUES
(1, 'Laptop', 'Elektronik', 5, 12000000),
(2, 'Mouse', 'Elektronik', 20, 150000),
(3, 'Meja', 'Furnitur', 3, 800000),
(4, 'Keyboard','Elektronik', 15, 400000),
(5, 'Kursi', 'Furnitur', 7, 1500000)
""")
# Window function: peringkat produk berdasarkan jumlah terjual per kategori
peringkat = con.execute("""
SELECT produk, kategori, jumlah,
RANK() OVER (PARTITION BY kategori ORDER BY jumlah DESC) AS peringkat
FROM penjualan
ORDER BY kategori, peringkat
""").df()
print(peringkat)
con.close()
Saat memakai koneksi file .duckdb, jangan lupa memanggil con.close() agar data benar-benar ter-flush ke disk. Cara lebih aman adalah memakai with duckdb.connect(...) as con: yang menutup koneksi otomatis.
Kesimpulan
DuckDB memberi kamu kekuatan SQL analitik tanpa ribetnya mengelola server database. Cukup satu library, kamu bisa membaca CSV/Parquet langsung, memadukan DataFrame Pandas dan Polars, serta menyimpan hasilnya dalam satu file .duckdb. Ini pilihan tepat untuk eksplorasi data, pembuatan laporan, hingga pipeline ETL ringan. Selamat mencoba dan selamat menganalisis data dengan lebih cepat! 🚀