- Artikel yang merangkum pola-pola praktis untuk menggunakan Postgres dengan lebih produktif dan aman
- Setiap pola memang kecil, tetapi jika dikumpulkan akan menghasilkan perbedaan besar
Menggunakan primary key UUID
- Karena UUID bersifat acak, ada kekurangan dari sisi pengurutan dan performa indeks
- Memakan ruang lebih banyak dibanding ID numerik
- Namun, ada kelebihan seperti berikut
- UUID dapat dibuat tanpa terhubung ke DB
- Aman untuk diekspos ke pihak luar
- Dengan
gen_random_uuid(), UUID bisa dibuat otomatis sebagai primary key
Selalu tambahkan field created_at dan updated_at
- Saat debugging, sangat berguna untuk mengetahui kapan record dibuat dan diubah
updated_at dapat diatur agar diperbarui otomatis melalui trigger
- Fungsinya cukup dibuat sekali, tetapi trigger harus diterapkan ke setiap tabel
Atur on update/delete restrict pada foreign key
- Saat menetapkan constraint foreign key, sebaiknya selalu menggunakan
on update restrict on delete restrict
- Ini mencegah terjadinya penghapusan berantai secara tidak sengaja saat data dihapus
- Ruang penyimpanan itu murah, tetapi pemulihan data sangat sulit, jadi lebih baik bersikap konservatif
Disarankan menggunakan schema
- Schema default adalah
public, tetapi ketika aplikasi membesar, sebaiknya dipisahkan ke schema tersendiri
- Schema bekerja seperti namespace, dan join juga bisa dilakukan antar-schema yang berbeda
- Semakin banyak jumlah tabel, semakin menguntungkan penggunaan schema untuk keterbacaan dan pemeliharaan
Gunakan pola enum table
- Dibanding enum type atau check constraint milik PostgreSQL, pendekatan memakai enum table lebih fleksibel
- Jika nilai enum dikelola di tabel terpisah, metadata bisa ditambahkan atau nilai enum diperluas dengan mudah
- Constraint tetap dijaga dengan mereferensikan nilai dari enum table melalui foreign key
Gunakan nama tabel dalam bentuk tunggal
- Sebaiknya nama tabel menggunakan bentuk tunggal, bukan jamak
- Saat menulis query, bentuk tunggal lebih jelas, sedangkan bentuk jamak dapat menimbulkan kebingungan makna
Beri nama join table secara mekanis
- Untuk join table pada relasi many-to-many, paling aman dan jelas jika menamainya dengan menggabungkan dua nama tabel
- Contoh:
person_pet
- Tambahkan unique index pada kombinasi tersebut untuk mencegah duplikasi
Gunakan soft delete alih-alih delete
- Daripada benar-benar menghapus data, lebih baik gunakan field timestamp seperti
revoked_at yang menunjukkan kapan data dihapus
- Ini memungkinkan pelacakan bukan hanya apakah data dihapus, tetapi juga kapan penghapusan terjadi
- Timestamp memberikan informasi lebih banyak dibanding nilai Boolean
Representasikan status dengan log table
- Alih-alih menyatakan status dengan satu kolom, simpan riwayat perubahan status di tabel terpisah
- Waktu terjadinya status dinyatakan secara eksplisit melalui kolom
valid_at
- Agar status terbaru bisa diambil dengan cepat, atur flag
latest serta unique index + trigger
- Ini menguntungkan dalam pemrosesan event asinkron atau situasi ketika urutan bisa tercampur
Tambahkan system_id pada baris khusus
- Selain enum table, kadang ada kebutuhan akan "baris sistem" tertentu
- Tambahkan field teks
system_id yang nullable lalu atur unique index
- Dengan
system_id, baris tertentu bisa diambil secara jelas
Gunakan view seminimal mungkin
- View berguna untuk mengabstraksikan query yang kompleks, tetapi sulit dipelihara
- Jika kolom dihapus, view perlu dibuat ulang
- Jika membuat view di atas view, bisa timbul masalah performa dan keterbacaan
- Gunakan secukupnya dan dengan hati-hati
Manfaatkan query JSON secara aktif
- Postgres bukan hanya kuat untuk menyimpan JSON, tetapi juga sangat andal untuk query yang mengembalikan JSON
- Relasi bertingkat bisa dikembalikan dalam bentuk JSON lewat satu query saja
- Semua data yang dibutuhkan bisa diambil sekaligus tanpa masalah N+1
- Kekurangan: informasi tipe hilang, dan seluruh data harus dimuat ke memori sekaligus
- Namun dari sisi performa maupun struktur, keuntungannya lebih besar
4 komentar
> Tabel join diberi nama secara mekanis
Menurut saya, fakta bahwa ada aturan penamaan seperti ini sendiri sudah bagus~
Kalau mempertimbangkan UUID7, bukankah itu bisa diurutkan berdasarkan waktu?
Sepertinya artikel tentang penggunaan UUID sebagai kunci utama di PostgreSQL juga layak dijadikan referensi.
Cara menambahkan timestamp saat melakukan soft delete bagus juga. Jika menggunakan UUID sebagai primary key, data tidak bisa diurutkan berdasarkan waktu, jadi sepertinya memakai snowflake id atau ulid juga merupakan pilihan yang baik. Namun dalam kasus ini, tiap server memang harus menyimpan sequence number.