chapter_05.
md 2026-05-03
chapter_05
Mantap Gan! Semangatnya luar biasa. Kita langsung masuk ke Chapter 5: Data Ingestion, Bulk Loading,
and Data Quality.
Di dunia nyata, data GIS itu jarang sekali yang bersih. Biasanya kita dapat "kiriman" dari vendor atau dinas lain
berupa ratusan file Shapefile atau GeoJSON yang kadang isinya tumpang tindih (overlap), koordinatnya
melenceng, atau geometrinya cacat. Bab ini akan mengajarkan peserta cara membangun "Pabrik Pengolahan
Data" (ELT Pipeline) di dalam database untuk mencuci data kotor tersebut sebelum masuk ke tabel produksi.
Sesuai request, porsi Lab saya buat ekstra panjang dan berbobot (Extended). Kita tidak cuma main SQL, tapi
akan mempraktikkan simulasi pipeline pembersihan data dan menggunakan tools wajib di industri: ogr2ogr.
Berikut materi, slide, dan instruksi lab-nya.
Chapter 5: Data Ingestion, Bulk Loading, and Data Quality
(Format Slide Presentasi & Speaker Notes)
Slide 1: Title Slide
Main Title: Chapter 5 — Data Ingestion, Bulk Loading, and Data Quality
Subtitle: Building robust pipelines for messy spatial data.
Speaker Notes:
"Selamat pagi/siang. Selamat datang di Chapter 5. Sejauh ini kita sudah bisa membuat tabel dan
melakukan query super cepat. Pertanyaannya: dari mana datanya berasal? Di bab ini, kita akan
belajar cara memasukkan jutaan data dari luar ke dalam database kita dengan aman, dan yang
terpenting: dalam keadaan bersih."
Slide 2: Chapter Objectives
Heading: Learning Objectives
Bullet Points:
Design an ELT (Extract, Load, Transform) architecture utilizing staging schemas.
Ingest massive spatial datasets rapidly using PostgreSQL COPY and ogr2ogr CLI.
Automate the repairing of messy vendor data (ST_MakeValid, ST_SnapToGrid).
Build an idempotent UPSERT pipeline (ON CONFLICT) for daily automated data merging.
Speaker Notes:
"Target di Chapter 5 adalah membangun pabrik pengolahan data. Karena data dari luar itu sering
kotor dan cacat, di akhir sesi ini Bapak/Ibu akan mampu membangun pipeline yang menyedot
1 / 13
chapter_05.md 2026-05-03
data mentah secara kilat, mencucinya secara otomatis di database, dan memindahkannya ke
tabel produksi tanpa menghasilkan data duplikat."
Slide 2: The Data Ingestion Challenge
Heading: Why Spatial Ingestion is Hard
Bullet Points:
Data comes from multiple sources (Vendors, Drones, IoT, Legacy Systems).
Formats vary wildly.
The Garbage In, Garbage Out (GIGO) Rule: Inserting invalid geometries will crash your
downstream analytical queries.
Standard INSERT INTO statements are too slow for millions of rows.
Speaker Notes:
"Mengambil data spasial itu ibarat meminum air dari selang pemadam kebakaran. Datanya besar,
formatnya beda-beda, dan sering kali 'kotor'. Kalau data kotor ini lolos masuk ke tabel utama,
query analitik kita di bab sebelumnya pasti akan error. Kita butuh strategi khusus."
Slide 3: Common Spatial Formats (The Legacy)
Heading: The Shapefile (.shp)
Bullet Points:
Invented by ESRI in the 1990s. Still the most common format today.
Pros: Supported by literally every GIS software.
Cons: Not just one file (needs .shx, .dbf, .prj). Limits on file size (2GB) and column name
length (10 chars).
Speaker Notes:
"Format pertama yang pasti Bapak/Ibu temui adalah Shapefile. Ini format fosil dari tahun 90-an
tapi masih jadi standar industri. Ingat, Shapefile itu bukan satu file. Kalau ada vendor kirim file
.shp saja tanpa .dbf atau .prj-nya, minta kirim ulang, karena datanya tidak akan bisa dibaca."
Slide 4: Common Spatial Formats (The Modern Web)
Heading: GeoJSON
Bullet Points:
The standard for web mapping and REST APIs.
Pros: Human-readable, single file, universally understood by web developers.
2 / 13
chapter_05.md 2026-05-03
Cons: Bulky (large file size), lacks spatial indexing inside the file, strict rules (must be EPSG:4326).
Speaker Notes:
"Kalau berurusan dengan developer backend atau API, pasti pakai GeoJSON. Formatnya mudah
dibaca manusia. Tapi ingat, GeoJSON itu wajib pakai koordinat derajat (WGS 84 / 4326). Jangan
pernah taruh koordinat meter (UTM) di dalam GeoJSON, nanti petanya tidak muncul di web."
Slide 5: Common Spatial Formats (The Developer's Choice)
Heading: CSV with WKT / Coordinates
Bullet Points:
CSV (Comma Separated Values): Simple tabular data.
Spatial aspect handled either by X, Y columns or a single WKT column.
Pros: Extremely lightweight, perfect for massive GPS point logs.
Cons: No embedded CRS/SRID information. You must define it during import.
Speaker Notes:
"Untuk data berjumlah puluhan juta baris seperti log GPS kendaraan, format paling masuk akal
adalah CSV. Sangat ringan. Tapi hati-hati, CSV tidak punya metadata sistem koordinat. Kitalah
yang harus mendefinisikan SRID-nya saat di-import ke PostGIS."
Slide 6: The "Direct Insert" Anti-Pattern
Heading: How NOT to Load Data
Bullet Points:
Running millions of INSERT INTO my_table VALUES (...) one by one.
Why it’s bad: Generates massive transaction logs (WAL bloat), kills disk I/O, and blocks other
users.
If one row has an invalid geometry, the entire transaction might fail.
Speaker Notes:
"Kesalahan fatal programmer pemula: memasukkan sejuta baris data menggunakan looping
INSERT dari aplikasi. Itu akan membuat hardisk server 'menjerit' dan memblokir akses pengguna
lain. Kalau di baris ke-999.000 ada satu titik yang rusak, seluruh prosesnya rollback (gagal). Waktu
Anda terbuang percuma."
Slide 7: PostgreSQL COPY Command
Heading: Bulk Loading at the Speed of Light
Bullet Points:
3 / 13
chapter_05.md 2026-05-03
The native PostgreSQL command for bulk ingestion.
Streams data directly into the database engine, bypassing standard SQL overhead.
COPY my_table FROM '/path/to/[Link]' DELIMITER ',' CSV HEADER;
Can ingest millions of rows in seconds.
Speaker Notes:
"Gunakan perintah bawaan PostgreSQL yaitu COPY. COPY ini menembak data langsung ke jantung
database tanpa lewat antrean SQL biasa. Sejuta data CSV bisa masuk hanya dalam hitungan
detik."
Slide 8: Introduction to GDAL and ogr2ogr
Heading: The Swiss Army Knife of GIS
Bullet Points:
GDAL (Geospatial Data Abstraction Library) is the open-source engine powering almost all GIS
tools (including QGIS and PostGIS itself).
ogr2ogr: A command-line tool for converting simple features data between file formats and
databases.
Example: Converting a Shapefile directly into a PostGIS table.
Speaker Notes:
"Selain perintah SQL, sebagai Engineer kita punya senjata pamungkas di command line Linux:
ogr2ogr. Ini adalah 'pisau lipat Swiss'-nya orang GIS. Ia bisa membaca hampir 100 format data
GIS yang berbeda dan langsung mendorongnya masuk ke tabel PostGIS tanpa kita perlu repot
coding."
Slide 9: ELT vs ETL
Heading: Extract, LOAD, Transform
Bullet Points:
ETL (Old way): Extract data -> Clean it in memory (Python/FME) -> Load to DB. (Slow, memory
limited).
ELT (Modern way): Extract data -> Load "dirty" data to DB -> Transform/Clean it using PostGIS
SQL power.
Leverages the massive CPU/RAM power of the database server.
Speaker Notes:
"Dulu kita pakai metode ETL. Datanya dicuci dulu pakai aplikasi di laptop, baru dimasukkan ke
server. Kalau datanya 50GB, laptopnya hang. Sekarang trennya ELT. Datanya kita tarik (Extract),
4 / 13
chapter_05.md 2026-05-03
kita buang mentah-mentah ke server (Load), lalu kita cuci menggunakan kekuatan ratusan fungsi
PostGIS (Transform). Server database jauh lebih kuat dari laptop kita."
Slide 10: The Staging Architecture
Heading: Building a Quarantine Zone
Bullet Points:
Never load external data directly into public.production_table.
Create a schema named staging.
Load raw data into staging.raw_vendor_data (Drop all constraints and indexes for maximum
load speed).
Speaker Notes:
"Jangan pernah import data luar langsung ke tabel produksi utama. Buatlah area karantina yang
kita sebut staging. Di area ini, kita matikan semua aturan index dan constraint agar data bisa
disedot masuk secepat mungkin."
Slide 11: Step 1 of ELT: The Raw Load
Heading: Ingesting Without Prejudice
Bullet Points:
Create table with generic types: geom GEOMETRY (No SRID, No Type restriction).
Allow NULLs.
Use COPY or ogr2ogr to blast the data in.
Speaker Notes:
"Tahap pertama, buat tabel staging yang 'menerima apa adanya'. Tipe geometrinya jangan
dikunci. Biarkan data masuk dulu secepatnya. Setelah datanya duduk manis di database, baru kita
periksa."
Slide 12: Step 2 of ELT: Validation & Auditing
Heading: Finding the Dirty Data
Bullet Points:
Query the staging table to identify issues before moving to production.
SELECT count(*) FROM staging WHERE ST_IsValid(geom) = false;
Check for missing SRIDs (ST_SRID(geom) = 0).
Check for out-of-bounds coordinates (e.g., Latitude > 90).
5 / 13
chapter_05.md 2026-05-03
Speaker Notes:
"Tahap kedua: Audit. Kita query untuk mencari 'penjahatnya'. Berapa banyak poligon yang
menyilang dirinya sendiri? Berapa banyak data yang lupa dikasih sistem koordinat? PostGIS akan
memberikan laporan lengkap."
Slide 13: Step 2 of ELT: Data Repairing
Heading: Fixing Geometries on the Fly
Bullet Points:
ST_MakeValid: Attempts to fix invalid geometries (e.g., converts a bowtie polygon into a valid
MultiPolygon).
ST_SetSRID: Applies the correct spatial reference system if missing.
ST_RemoveRepeatedPoints: Cleans up overly dense/redundant vertices.
Speaker Notes:
"Daripada kita kembalikan datanya ke vendor dan minta diperbaiki, PostGIS punya fungsi
ST_MakeValid. Ia ibarat montir otomatis. Poligon yang cacat akan digunting dan dijahit ulang
sesuai kaidah matematika yang benar secara otomatis."
Slide 14: Step 2 of ELT: Snapping and Topology
Heading: Removing Gaps and Overlaps
Bullet Points:
Vendor data often has tiny microscopic gaps between adjacent parcels.
ST_SnapToGrid(geom, 0.001): Forces vertices to snap to a regular grid, eliminating
microscopic floating-point errors.
Speaker Notes:
"Sering kali, batas wilayah antar desa dari vendor itu kalau di-zoom maksimal ternyata ada celah
selebar 1 sentimeter atau tumpang tindih. Kita bisa merapikannya dengan ST_SnapToGrid,
memaksa titik-titik koordinat tersebut menempel pada satu grid yang konsisten."
Slide 15: Step 3 of ELT: Merge / Upsert
Heading: Moving to Production
Bullet Points:
The clean data is now ready for the strict production schema.
Use INSERT INTO ... SELECT ... FROM staging.
Only select valid data, apply ST_MakeValid during the transfer.
6 / 13
chapter_05.md 2026-05-03
Speaker Notes:
"Tahap ketiga: Pindah ke rumah utama. Kita insert dari tabel staging ke tabel produksi. Di proses
pemindahan ini, kita sekalian terapkan perbaikannya."
Slide 16: The Concept of Idempotency
Heading: Idempotent Data Loading
Bullet Points:
Idempotency: Running the same ingestion script 1 time or 100 times yields the exact same final
result (no duplicates).
Crucial for automated daily jobs (cron jobs / Apache Airflow).
If a job fails halfway, you can safely rerun it.
Speaker Notes:
"Ini konsep level senior: Idempotency. Artinya, kalau script import data kita jalankan dua kali
tanpa sengaja, datanya tidak boleh jadi dobel. Database harus cukup pintar untuk tahu mana
data baru, mana data yang cuma perlu di-update. Ini penting kalau kita pakai sistem otomatisasi
tiap malam."
Slide 17: Implementing UPSERT in PostgreSQL
Heading: INSERT ... ON CONFLICT
Bullet Points:
The PostgreSQL way to achieve idempotency.
Requires a Unique Index or Primary Key.
Logic: "Try to insert this spatial record. If the Asset ID already exists, UPDATE its geometry and
attributes instead."
Speaker Notes:
"Cara bikinnya pakai perintah ON CONFLICT. Kita beri tahu database, 'Tolong masukkan data halte
bus ini. Kalau ID haltenya sudah ada, jangan ditolak, tapi update koordinat lamanya dengan
koordinat baru ini'."
Slide 18: Materialized Views as Curated Data
Heading: The Data Mart Layer
Bullet Points:
The production table is highly normalized and strictly constrained.
Create a curated schema with MATERIALIZED VIEW.
7 / 13
chapter_05.md 2026-05-03
Denormalizes the data, applies spatial formatting (like GeoJSON conversion), and readies it for
API consumption.
Speaker Notes:
"Setelah data aman di tabel transaksi, kita buatkan Materialized View sebagai 'etalase toko' (Data
Mart). Aplikasi dashboard atau API tidak boleh baca tabel inti, mereka hanya boleh baca view
yang sudah dirapikan ini agar server tidak terbebani."
Slide 19: Chapter 5 Summary
Heading: Pipeline Best Practices
Bullet Points:
Never use basic loops for insertion; use COPY or ogr2ogr.
Embrace ELT: Extract, Load to a Staging Table, then Transform/Clean.
Use ST_MakeValid as a quality gate.
Ensure your ingestion pipelines are idempotent (ON CONFLICT).
Speaker Notes:
"Ringkasan Bab 5: Tinggalkan cara lama (ETL di laptop). Gunakan tabel Staging, cuci data Anda di
dalam database, dan pastikan script Anda bisa dijalankan berulang kali tanpa membuat data
ganda."
Slide 20: Lab 5 Introduction
Heading: Lab 5: The Enterprise Ingestion Pipeline
Bullet Points:
Simulating messy vendor data.
The Staging vs Production workflow.
Automating geometry repairs.
Building an idempotent UPSERT script.
Executing CLI ingestion with ogr2ogr.
Speaker Notes:
"Mari kita masuk ke Lab terpanjang kita. Kita akan bermain peran. Bapak/Ibu akan menerima data
kotor dari saya, dan tugas Bapak/Ibu adalah membangun pipeline pencucian data hingga data
tersebut aman masuk ke tabel produksi."
Sebelum masuk ke Lab, mari kita lihat simulasi interaktif bagaimana pipeline ELT ini bekerja menyaring dan
memperbaiki data.
8 / 13
chapter_05.md 2026-05-03
Did this visual help you understand the answer better?
Yes No
LAB MANUAL - CHAPTER 5
Building an Enterprise ELT Pipeline & Handling Messy Data
Lab Objective: Peserta akan membangun arsitektur Staging, melakukan bulk-load data kotor (cacat geometri
& duplikat), melakukan audit, memperbaiki data menggunakan fungsi PostGIS, melakukan UPSERT
(Idempotent), dan mencoba command-line ogr2ogr.
Part 1: Schema Setup (Staging vs Production)
Praktik terbaik di enterprise adalah memisahkan data mentah dari data produksi.
1. Buat Schema Baru di DBeaver:
SQL
CREATE SCHEMA IF NOT EXISTS staging;
CREATE SCHEMA IF NOT EXISTS prod;
2. Buat Tabel Produksi (Ketat & Bersih):
Tabel ini HARUS punya Primary Key dan tipe geometri yang di-set ketat.
SQL
CREATE TABLE prod.land_parcels (
parcel_id VARCHAR(50) PRIMARY KEY, -- Penting untuk UPSERT
owner_name VARCHAR(100),
geom GEOMETRY(MultiPolygon, 4326) -- Strict: MultiPolygon WGS84
);
3. Buat Tabel Staging (Longgar & Tanpa Constraint):
SQL
CREATE TABLE staging.raw_parcels (
raw_id VARCHAR(50),
owner_name VARCHAR(100),
geom GEOMETRY -- Longgar: Tipe apa saja boleh masuk, SRID bebas
);
9 / 13
chapter_05.md 2026-05-03
Part 2: Simulating Data Ingestion (The Dirty Data)
Kita akan mensimulasikan bahwa kita baru saja me-load ribuan data CSV menggunakan perintah COPY ke
tabel staging. Untuk lab ini, kita inject 4 baris data yang mewakili berbagai masalah umum.
1. Insert Data Kotor ke Staging:
SQL
INSERT INTO staging.raw_parcels (raw_id, owner_name, geom) VALUES
-- Kasus 1: Data Normal/Sempurna
('P-001', 'Bapak A', ST_GeomFromText('POLYGON((0 0, 10 0, 10 10, 0 10, 0
0))')),
-- Kasus 2: Invalid Geometry (Bentuk Pita / Bowtie)
('P-002', 'Ibu B', ST_GeomFromText('POLYGON((0 0, 10 10, 10 0, 0 10, 0
0))')),
-- Kasus 3: Bukan MultiPolygon (Hanya Polygon biasa)
('P-003', 'Bapak C', ST_GeomFromText('POLYGON((20 20, 30 20, 30 30, 20 30, 20
20))')),
-- Kasus 4: Data Duplikat (ID P-001 masuk lagi dengan nama pemilik berbeda)
('P-001', 'Pemilik Baru (Update)', ST_GeomFromText('POLYGON((0 0, 10 0, 10
10, 0 10, 0 0))'));
Part 3: The Audit & Quality Gate (Mencari Kerusakan)
Sebelum dioper ke tabel produksi, sebagai Data Engineer, kita wajib mengaudit staging.
1. Jalankan Audit Validitas Geometri:
SQL
SELECT
raw_id,
owner_name,
ST_IsValid(geom) AS is_valid,
ST_IsValidReason(geom) AS error_reason
FROM staging.raw_parcels;
✅ Analisis Output: Anda akan melihat P-002 berstatus false dengan alasan Self-intersection
(Garis saling silang). Jika data ini dipaksa masuk ke tabel produksi, fitur Spatial Index akan rusak/gagal.
Part 4: The Transformation & Upsert (Idempotent Merge)
10 / 13
chapter_05.md 2026-05-03
Ini adalah "Magic Script"-nya. Kita akan memindahkan data dari staging ke prod, sekaligus memperbaiki
error, mengubah Polygon jadi MultiPolygon, mengatur SRID menjadi 4326, dan menangani duplikasi P-001
secara otomatis!
1. Jalankan Skrip ELT (UPSERT):
SQL
INSERT INTO prod.land_parcels (parcel_id, owner_name, geom)
SELECT
raw_id,
owner_name,
-- Transformasi 3 Langkah:
-- 1. Set SRID ke 4326 (Anggap data mentah adalah WGS84)
-- 2. ST_MakeValid: Perbaiki yang rusak (Bowtie)
-- 3. ST_Multi: Konversi Polygon menjadi MultiPolygon agar masuk ke
aturan tabel
ST_Multi(ST_MakeValid(ST_SetSRID(geom, 4326)))
FROM staging.raw_parcels
-- Aturan Idempotency (ON CONFLICT)
ON CONFLICT (parcel_id)
DO UPDATE SET
owner_name = EXCLUDED.owner_name,
geom = [Link];
2. Verifikasi Hasil di Tabel Produksi:
SQL
SELECT * FROM prod.land_parcels ORDER BY parcel_id;
✅ Analisis Output: Cek tabel produksi Anda!
Hanya ada 3 baris (P-001, P-002, P-003). Duplikat P-001 tidak membuat sistem error, tapi
menimpa/update nama menjadi "Pemilik Baru". (Idempotency berhasil).
Semua geometri sekarang bertipe MULTIPOLYGON dan memiliki SRID 4326.
Coba cek validitasnya dengan ST_IsValid(geom), semuanya pasti true! P-002 sudah otomatis
dijahit ulang oleh PostGIS.
Part 5 (Extended): Command Line Ingestion using ogr2ogr
Sebagai Engineer sejati, kita harus keluar dari kenyamanan DBeaver GUI dan masuk ke Terminal/Console Linux
untuk automasi tingkat tinggi. Kita akan men-generate file GeoJSON di VM AlmaLinux, lalu mendorongnya
masuk ke PostGIS pakai tools CLI.
11 / 13
chapter_05.md 2026-05-03
(Instruksi ini dikerjakan di terminal SSH VM server1 Agan).
1. Instal GDAL (Jika belum ada di VM):
Bash
sudo dnf install -y gdal
2. Buat File GeoJSON Dummy di Server:
Kita akan membuat file teks GeoJSON secara instan. Copy-paste seluruh block ini ke terminal Agan lalu
tekan Enter:
Bash
cat <<EOF > data_jalan.geojson
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {"nama_jalan": "Jalan Merdeka", "tipe": "Arteri"},
"geometry": {"type": "LineString", "coordinates": [[106.8, -6.2],
[106.9, -6.2]]}
}
]
}
EOF
3. Jalankan Ingestion dengan ogr2ogr:
Kita akan mendorong data_jalan.geojson ini langsung menjadi tabel baru bernama jalan_baru di
dalam database gis_training.
Bash
ogr2ogr -f "PostgreSQL" PG:"dbname=gis_training user=postgres password=lab123
host=localhost" \
"data_jalan.geojson" \
-nln public.jalan_baru \
-nlt GEOMETRY \
-lco GEOMETRY_NAME=geom \
-overwrite
Keterangan parameter:
-f "PostgreSQL": Format tujuan.
12 / 13
chapter_05.md 2026-05-03
PG:"...": Connection string ke PostGIS.
-nln public.jalan_baru: Nama skema dan tabel yang akan otomatis dibuat.
-nlt GEOMETRY: Tipe data.
-overwrite: Menimpa tabel jika sudah ada (berguna untuk scripting harian).
4. Verifikasi Kembali di DBeaver:
Buka DBeaver, refresh tabel Anda (F5).
Jalankan: SELECT * FROM public.jalan_baru;
✅ Hasil: Anda akan melihat tabel jalan_baru sudah tercipta dengan sempurna, lengkap dengan
kolom nama_jalan, tipe, dan geometrinya, tanpa perlu menulis satu baris pun kode SQL CREATE
TABLE!
[End of Lab 5]
Gimana Gan? Dengan simulasi ELT Pipeline (Pencucian Data & UPSERT) ditambah praktik riil menggunakan
command line Linux (ogr2ogr), bobot Chapter 5 ini sangat merepresentasikan tantangan Data Engineer di
lingkungan Enterprise production.
Kalau materinya mantap dan siap bungkus, kita bisa lanjut ke ranah pengolahan piksel/satelit di Chapter 6:
Spatial Analytics and Raster Data in PostGIS!
13 / 13