- Property graph di Postgres 19 adalah fitur SQL/PGQ yang mendeklarasikan tabel yang sudah ada sebagai simpul dan sisi, lalu menelusuri pola relasi tetap dengan
MATCH, tanpa menyalin data atau membuat mesin eksekusi graf terpisah
- Pola graf dikompilasi menjadi join relasional sehingga langsung memanfaatkan optimizer, indeks, dan statistik yang sudah ada; akibatnya, traversal yang lambat pun bisa dianalisis dan dioptimalkan dengan cara yang sama seperti join biasa
- Tabel dimensi secara alami dipetakan ke simpul, tabel join murni ke sisi, tetapi tabel fakta yang punya beberapa foreign key dan properti sendiri lebih cocok dimodelkan sebagai simpul hub yang merepresentasikan event
- Satu tabel dapat dideklarasikan sekaligus sebagai simpul dan beberapa sisi dengan alias berbeda, sehingga tidak perlu membuat atau menyimpan tabel sisi terpisah yang memanfaatkan foreign key yang sudah ada di
results
- Karena Postgres 19 belum mendukung path dengan panjang variabel, fitur ini tidak cocok untuk shortest path, reachability N-hop, atau PageRank, dan lebih tepat untuk traversal panjang tetap ketika struktur relasinya sudah diketahui
Cara membaca skema relasional sebagai graf
- Dalam skema relasional yang ternormalisasi, tabel dimensi seperti
drivers, constructors, dan circuits menyimpan entitas, sedangkan tabel fakta mencatat event seperti hasil balapan atau sesi kualifikasi
- Setiap baris adalah simpul potensial, dan foreign key adalah sisi potensial yang menunjuk ke baris lain
- Diagram ER setara dengan graf pada level skema
- Baris aktual dan relasi foreign key setara dengan graf pada level instance
- Permintaan seperti “mencari constructor untuk setiap result” pada dasarnya adalah traversal graf yang dalam SQL relasional ditulis sebagai
results JOIN constructors ON ...
- SQL/PGQ tidak menambahkan graf baru sebagai penyimpanan terpisah, melainkan memungkinkan kita menulis pertanyaan dalam bentuk graf alih-alih mencantumkan join secara langsung
- Pendekatan RelBench membawa tabel ke pandas lalu menyusun graf PyTorch di memori, sedangkan property graph Postgres langsung menggunakan relasi antar tabel yang sudah ada di dalam database
- Contoh di PyG juga umumnya memakai file datar atau graf di memori
- Kode eksperimen dengan dataset Formula 1 bisa dilihat di repositori GitHub
Susunan property graph
CREATE PROPERTY GRAPH adalah objek deklaratif bernama yang dibuat di atas tabel yang sudah ada
VERTEX TABLES menentukan tabel yang baris-barisnya dibaca sebagai simpul
EDGE TABLES menentukan tabel yang baris-barisnya dibaca sebagai relasi penghubung
- Untuk setiap tabel simpul, elemen berikut didefinisikan
KEY: identitas simpul, biasanya memakai primary key
LABEL: nama tipe simpul yang dipakai dalam MATCH
PROPERTIES: daftar kolom yang bisa diakses dalam query graf
- Untuk setiap tabel sisi, ditentukan
SOURCE dan DESTINATION, yang masing-masing merujuk ke key simpul
CREATE PROPERTY GRAPH tidak memindahkan atau menyalin data
- Baris tetap berada di tabel asal
- Deklarasi ini hanya mendefinisikan cara membaca struktur foreign key yang sudah ada sebagai graf
- Unsur struktural property graph hanya terdiri dari dua jenis: simpul dan sisi
- Label dan properti adalah atribut yang melekat pada simpul atau sisi
- Di
psql, Element Kind untuk tiap elemen hanya akan berupa vertex atau edge
Mengueri pola tetap dengan MATCH
- Query graf ditulis dengan menempatkan pola
MATCH di dalam GRAPH_TABLE(...)
- Pola berikut merepresentasikan relasi dari driver ke race melalui result
MATCH (d IS driver)<-[IS of_driver]-(res IS result)-[IS in_race]->(ra IS race)
- Klausa
COLUMNS menentukan kolom yang akan dikembalikan query graf ke luar
- Pada
SELECT luar, hasil GRAPH_TABLE(...) bisa diperlakukan seperti tabel biasa
- Karena pola memuat arah dan label, relasinya bisa dibaca seperti kalimat sehingga struktur lebih mudah dipahami dibanding multi-join yang setara
Struktur yang diubah menjadi join relasional saat dieksekusi
MATCH bukan mesin eksekusi graf terpisah yang ditempelkan ke Postgres, melainkan sintaks yang dikompilasi menjadi join relasional
- Saat
EXPLAIN dijalankan pada pola driver–result–race, akan muncul empat hash join terhadap tabel dasar
- Sama seperti join yang ditulis langsung, ia memakai
- optimizer Postgres yang sudah ada
- indeks yang sudah ada
- statistik yang sudah ada
- Jika traversal graf lambat, penyebab dan cara optimasinya pun sama seperti ketika join biasa lambat
- Di
psql, graf juga bisa diperiksa dengan perintah yang mirip tabel
\dG: menampilkan daftar property graph
\d f1: menampilkan tiap simpul dan sisi, tabel dasar, jenis elemen, serta simpul asal dan tujuan untuk sisi
\d+ f1: merekonstruksi seluruh pernyataan CREATE PROPERTY GRAPH, termasuk key sisi yang diinferensikan dari primary key tabel sisi
Perbedaan key dan properti
- Kolom yang ditetapkan sebagai
KEY simpul tidak otomatis menjadi properti
- Jika
driver_id hanya ditetapkan sebagai key simpul lalu difilter dengan d.driver_id = 1, query akan gagal karena kolom itu bukan properti yang dapat diakses
- Key mengidentifikasi simpul, tetapi tidak otomatis diekspos ke query
- Jika kolom ID ingin difilter atau dikembalikan, kolom itu harus ditambahkan secara eksplisit ke daftar
PROPERTIES
Batasan path panjang variabel di Postgres 19
- Postgres 19 belum mendukung quantifier pola elemen seperti mengikuti sisi 1 sampai 3 kali
ERROR: element pattern quantifier is not supported
- Untuk menelusuri dua hop, dua pola sisi harus ditulis eksplisit di
MATCH
- Path dengan panjang arbitrer tidak bisa diekspresikan dengan sintaks property graph
- Traversal dengan kedalaman terbuka harus ditangani dengan recursive CTE pada tabel dasar, yang berarti keluar dari sintaks property graph
Memetakan tabel yang ada ke simpul dan sisi
-
Tabel dimensi sebagai simpul
- Tabel entitas seperti
drivers, constructors, dan circuits yang punya primary key stabil serta atribut sendiri dipetakan langsung sebagai simpul
- Cukup gunakan primary key sebagai key simpul dan ekspos kolom yang diperlukan sebagai properti
-
Tabel join murni sebagai sisi
- Tabel bridge many-to-many seperti
student_courses(student_id, course_id) secara alami dipetakan sebagai sisi karena peran aslinya memang menghubungkan dua entitas
- Satu foreign key dideklarasikan sebagai simpul asal, dan foreign key lainnya sebagai simpul tujuan
- Karena setiap baris tabel join itu sendiri sudah merepresentasikan satu relasi, tidak perlu transformasi data khusus untuk graf
- Dalam struktur ini,
students dan courses menjadi simpul, sedangkan student_courses menjadi sisi enrolled_in
-
Tabel fakta sebagai simpul event
- Baris
results menunjuk ke tiga entitas—driver, race, dan constructor—sekaligus menyimpan datanya sendiri seperti grid, position, points, dan status
- Karena sisi SQL/PGQ adalah relasi biner yang hanya punya satu titik asal dan satu titik tujuan, satu baris utuh dengan tiga foreign key tidak bisa dijadikan satu sisi tunggal
- Jika baris fakta itu sendiri menjadi objek analisis, lebih cocok mendeklarasikan tabel tersebut sebagai simpul
- Simpul
results menyimpan event beserta propertinya
- Sisi sempit seperti
results_driver, results_race, dan results_constructor menghubungkannya ke entitas luar
- Model ini membentuk struktur hub seperti
driver <- result -> race, sehingga kita bisa berhenti di simpul result untuk memfilter atau mengambil propertinya
- Jika yang menjadi perhatian adalah relasinya, modelkan sebagai sisi; jika yang menjadi perhatian adalah baris atau event tertentu yang punya properti sendiri, modelkan sebagai simpul
- Tabel join merepresentasikan relasi, sedangkan tabel fakta merepresentasikan event
Menggunakan satu tabel sekaligus sebagai simpul dan sisi
- Pembedaan “simpul atau sisi” berlaku pada tiap deklarasi elemen dalam graf, bukan pada tabel dasar itu sendiri
- Satu tabel dapat dideklarasikan di
VERTEX TABLES dan EDGE TABLES sekaligus dengan alias berbeda
results bisa dipakai sebagai simpul result sambil memakai tabel yang sama kembali dengan alias sisi berikut
results AS res_driver: menghubungkan result ke driver
results AS res_race: menghubungkan result ke race
results AS res_constr: menghubungkan result ke constructor
- Setiap alias sisi menggunakan kolom primary key dan foreign key yang memang sudah ada di
results
- Tidak perlu membuat tabel
results_driver, results_race, atau results_constructor yang terpisah, dan alias tidak menyimpan data
- Tabel fakta dengan tiga foreign key harus dideklarasikan sebagai tiga alias sisi, masing-masing dengan satu titik asal dan satu titik tujuan, bukan sebagai satu sisi multi-endpoint
- Pendekatan ini memakai tiga alias deklaratif atas satu tabel dasar, bukan tiga tabel fisik atau view terpisah
Konflik nama dan tipe properti
- Jika
PROPERTIES dihilangkan, SQL/PGQ akan mengekspos semua kolom tabel sebagai properti
- Jika
results dan qualifying sama-sama punya kolom number, tetapi tipe datanya double precision dan bigint, akan muncul error berikut
ERROR: property "number" data type mismatch: double precision vs. bigint
- Di seluruh graf, properti dengan nama yang sama harus memiliki satu tipe yang sama, sehingga kolom bernama sama tetapi bertipe berbeda akan bentrok
- Dengan mencantumkan hanya kolom yang dibutuhkan di
PROPERTIES, kolom yang bentrok bisa dikeluarkan dari graf
- Masalah key yang tidak otomatis menjadi properti dan konflik tipe sama-sama bisa diselesaikan dengan allowlist properti yang eksplisit
Query yang cocok dan yang tidak cocok
-
Pola relasi tetap
- Property graph cocok untuk pertanyaan seperti “temukan target yang terhubung ke X dengan pola tertentu ini”
- Dalam graf Formula 1, kita bisa menulis query seperti
- menelusuri constructor tempat driver tertentu pernah membalap
- mencari rival melalui pola dari driver ke result dan race, lalu ke result dan driver lain
- memfilter sekaligus berdasarkan struktur dan properti, misalnya hasil dengan posisi start di luar 10 besar dan driver berkebangsaan Italian
- Ketika bentuk relasi sudah diketahui sebelumnya dan strukturnya tetap serta terbatas, sintaks pencarian, filter, dan agregasi menjadi lebih mudah dibaca
- Query yang memerlukan self-join berulang pun bisa diekspresikan lebih jelas dengan satu pola
MATCH
-
Masalah ketika path itu sendiri belum diketahui
- Masalah berikut tidak cocok untuk property graph di Postgres 19
- shortest path antara dua driver
- semua target yang dapat dicapai dalam N-hop
- penelusuran konektivitas dengan kedalaman yang tidak diketahui sebelumnya
- Query semacam ini memerlukan traversal panjang variabel, sehingga harus memakai recursive CTE pada tabel dasar
- Algoritme graf seperti PageRank, deteksi komunitas, dan perhitungan sentralitas juga merupakan masalah yang berbeda dari pattern matching, jadi tidak termasuk cakupan fitur ini
- Property graph bisa mencari target yang terhubung ketika struktur path-nya sudah diketahui, tetapi tidak bisa menemukan path ketika kita belum tahu X dan Y terhubung melalui jalur apa, atau menghitung pentingnya struktur dalam graf
Hal yang perlu dipertimbangkan sebelum mengadopsi
- SQL/PGQ adalah overlay deklaratif di atas struktur foreign key yang sudah ada, dan tidak menyimpan data tambahan kecuali dipilih secara khusus
- Ada dua manfaat utama
- traversal berbentuk tetap bisa ditulis lebih mudah dibaca dibanding join relasional
- ia menyediakan objek bernama untuk mendokumentasikan skema sebagai graf
- Batasan terbesarnya adalah tidak adanya path panjang variabel, sehingga penelusuran yang dalam atau terbuka harus ditangani dengan SQL rekursif
- Tabel pada dasarnya tidak inheren sebagai simpul atau sisi; pada setiap graf, kita bisa menentukan apakah barisnya dibaca sebagai simpul, sisi, atau keduanya
- Jika ingin mengueri pola graf tetap pada skema yang sudah ada di Postgres 19,
CREATE PROPERTY GRAPH dan MATCH layak dipertimbangkan sebelum memindahkan data ke database graf terpisah
- Jika perlu menelusuri kedalaman yang tidak diketahui, recursive CTE tetap dibutuhkan, tetapi apa pun pendekatannya, data tidak perlu keluar dari Postgres
- Sebelum benar-benar mengadopsinya, performanya tetap perlu diuji langsung sesuai kebutuhan
Belum ada komentar.