Topik ini membandingkan ORM dengan SQL yang ditulis langsung, bukan untuk memilih pemenangnya, melainkan untuk menegaskan apa yang diotomatisasi dan apa yang disembunyikan. Pembandingnya SQLAlchemy pada Python sebagai representasi ORM yang mapan, dan fondasi schema yang dibangun tangan sepanjang jalur ini menjadi dasar menilai kerja ORM.
Blok penyiapan dataset#
# siapkan ulang tabel dan data contoh untuk topik ini
PGOPTIONS='-c client_min_messages=warning' psql -q -U postgres -d perpustakaan <<'SQL'
DROP TABLE IF EXISTS peminjaman, buku, anggota, kategori CASCADE;
CREATE TABLE kategori (id SERIAL PRIMARY KEY, nama TEXT NOT NULL UNIQUE);
CREATE TABLE anggota (id SERIAL PRIMARY KEY, nama TEXT NOT NULL, email TEXT UNIQUE, bergabung DATE NOT NULL, aktif BOOLEAN NOT NULL DEFAULT TRUE);
CREATE TABLE buku (id SERIAL PRIMARY KEY, judul TEXT NOT NULL, penulis TEXT NOT NULL, tahun INTEGER NOT NULL, kategori_id INTEGER REFERENCES kategori(id));
CREATE TABLE peminjaman (id SERIAL PRIMARY KEY, anggota_id INTEGER NOT NULL REFERENCES anggota(id), buku_id INTEGER NOT NULL REFERENCES buku(id), tanggal_pinjam DATE NOT NULL, tanggal_kembali DATE);
INSERT INTO kategori (nama) VALUES ('Pemrograman'), ('Sains'), ('Sejarah'), ('Fiksi'), ('Statistika');
INSERT INTO anggota (nama, email, bergabung, aktif) VALUES ('Ali Rahman', '[email protected]', '2024-01-15', TRUE), ('Budi Santoso', '[email protected]', '2024-03-02', TRUE), ('Citra Kirana', '[email protected]', '2024-05-20', FALSE), ('Dewi Lestari', '[email protected]', '2024-08-11', TRUE), ('Eka Pratama', NULL, '2025-01-30', TRUE);
INSERT INTO buku (judul, penulis, tahun, kategori_id) VALUES ('Dasar Basis Data', 'Sari Wulandari', 2021, 1), ('Jaringan Komputer', 'Ahmad Fauzi', 2019, 1), ('Fisika untuk Pemula', 'Rina Marlina', 2020, 2), ('Kimia Organik', 'Rina Marlina', 2022, 2), ('Sejarah Nusantara', 'Bambang Wijaya', 2018, 3), ('Cerita Kota Lama', 'Nur Aisyah', 2023, 4), ('Statistika Terapan', 'Sari Wulandari', 2022, 5), ('Algoritma dan Struktur Data', 'Ahmad Fauzi', 2021, 1);
INSERT INTO peminjaman (anggota_id, buku_id, tanggal_pinjam, tanggal_kembali) VALUES (1, 1, '2025-03-01', '2025-03-15'), (1, 7, '2025-03-05', '2025-03-20'), (2, 3, '2025-03-10', NULL), (3, 5, '2025-02-20', '2025-03-01'), (2, 1, '2025-04-02', NULL), (4, 6, '2025-04-07', NULL), (5, 8, '2025-04-09', '2025-04-25'), (4, 2, '2025-05-01', NULL);
SQLApa yang diotomatisasi ORM#
ORM memetakan baris menjadi objek, sehingga pembacaan dan penulisan kolom menjadi atribut pada kode, dan perubahan kecil ditetapkan melalui unit kerjanya tanpa teks SQL. Bentuk lain otomatisasinya adalah relasi, yaitu pemanggilan yang menyusuri foreign key tanpa join yang ditulis tangan, serta pembuatan skema dari definisi model yang berpasangan dengan alat migration-nya.
Blok berikut menunjukkan padanan SQL untuk pekerjaan pembacaan yang paling umum, yaitu daftar dengan relasinya, yang pada ORM ditulis sebagai satu akses atribut.
# padanan SQL dari akses relasi ORM
psql -U postgres -d perpustakaan -c "SELECT a.nama, b.judul, p.tanggal_pinjam FROM peminjaman p JOIN anggota a ON p.anggota_id = a.id JOIN buku b ON p.buku_id = b.id WHERE p.tanggal_kembali IS NULL ORDER BY p.id;" nama | judul | tanggal_pinjam
--------------+---------------------+----------------
Budi Santoso | Fisika untuk Pemula | 2025-03-10
Budi Santoso | Dasar Basis Data | 2025-04-02
Dewi Lestari | Cerita Kota Lama | 2025-04-07
Dewi Lestari | Jaringan Komputer | 2025-05-01
(4 rows)Dua join dan syaratnya otomatis disusun ORM dari deklarasi relasinya, dan itulah manfaat yang sebenarnya, yaitu kesalahan penulisan join menghilang pada pola yang berulang. Nilai ini nyata pada CRUD, sedangkan pembeda yang berikutnya menentukan batasnya.
Apa yang disembunyikan ORM#
Kepandaian ORM menyembunyikan SQL yang benar-benar dikirim, dan penyembunyiannya memunculkan tiga kelas persoalan yang berulang. Kelas pertama adalah N+1 yang dibedah pada modul anti-pola, karena akses relasi per butir mengirim satu query per butir tanpa terlihat dari kodenya, dan solusi eager loading-nya harus diingat secara sadar.
Kelas kedua adalah query kompleks yang dipaksakan ke sintaks ORM, sehingga window function, grouping set, dan CTE yang dibahas pada modul subquery menjadi terbaca lebih sulit daripada SQL-nya sendiri. Kelas ketiga adalah performa yang dinilai tanpa rencana eksekusi, karena perencana menilai SQL, bukan kode ORM, dan kemampuan membaca EXPLAIN tetap menjadi keterampilan yang tidak digantikan apa pun.
# nilai laporan dengan SQL langsung pada fungsi jendela
psql -U postgres -d perpustakaan -c "SELECT nama, pinjaman, NTILE(2) OVER (ORDER BY pinjaman DESC, nama) AS tingkat FROM (SELECT a.nama, COUNT(p.id) AS pinjaman FROM anggota a LEFT JOIN peminjaman p ON p.anggota_id = a.id GROUP BY a.nama) t ORDER BY tingkat, pinjaman DESC, nama;" nama | pinjaman | tingkat
--------------+----------+---------
Ali Rahman | 2 | 1
Budi Santoso | 2 | 1
Dewi Lestari | 2 | 1
Citra Kirana | 1 | 2
Eka Pratama | 1 | 2
(5 rows)Laporan pembagian tingkat keaktifan ini ditulis dalam empat baris SQL yang jelas, sedangkan padanan sintaks ORM-nya menuntut konstruksi bersarang yang panjang, contoh nyata dari wilayah yang lebih jujur dibiarkan SQL. SQLAlchemy menyediakan pintu teks mentah untuk kebutuhan ini, dan pemakaian pintunya bukan kekalahan melainkan pemilihan alat per pekerjaan.
Hibrid sebagai kebiasaan kerja#
Kebiasaan yang bertahan di industri adalah hibrid, yaitu ORM untuk pemetaan baris, CRUD, dan relasi sederhana, sedangkan SQL langsung untuk laporan, pembaruan massal, dan query yang rencananya dipahami sampai ke simpulnya. Keduanya berbagi satu koneksi dan satu transaksi, sehingga penulisan campuran tetap memakai disiplin transaksi yang sama.
Keputusan per bagian kode mengikuti dua pertanyaan, yaitu apakah pemetaan objeknya benar-benar dipakai, dan apakah SQL yang dihasilkannya dipahami. Jawaban kosong pada pertanyaan pertama mengarah ke SQL langsung, sedangkan jawaban kosong pada pertanyaan kedua menuntut pembacaan log yang diaktifkan pada ORM untuk mengungkapkan SQL-nya, kebiasaan yang menutup celah penyembunyiannya.
Kesalahan umum#
Kesalahan pertama adalah membiarkan ORM mendefinisikan skema tanpa pemahaman constraint, sehingga foreign key dan CHECK yang tidak didukung penuh hilang diam-diam, dan skema yang ditulis tangan sepanjang jalur ini menjadi penawarnya. Kesalahan kedua adalah menyalahkan ORM atas N+1, padahal kuncinya pola akses yang dibaca pada log, dan eager loading adalah keputusan per pemakaian.
Kesalahan ketiga adalah memakai ORM untuk pemuatan massal per objek, biaya yang seharusnya COPY atau executemany pada modul manipulasi data. Kesalahan keempat adalah dua alat migration yang berjalan bersamaan, yaitu skema dari model ORM dan skema tangan yang menggeser, sehingga keduanya saling menimpa, dan satu sumber kebenaran skema dipilih sejak awal.
Ringkasan#
- ORM mengotomatisasi pemetaan baris ke objek, penyusunan join dari relasi, dan pembuatan skema dari model.
- N+1, query kompleks yang dipaksakan, dan penilaian performa tanpa rencana adalah tiga harga penyembunyiannya.
- Laporan, agregasi, dan pembaruan massal lebih jujur ditulis sebagai SQL langsung, dan pintu teks mentah ORM sah dipakai.
- Kebiasaan hibrid membagi pekerjaan per sifatnya, dengan satu koneksi, satu transaksi, dan satu sumber skema.
Referensi#
- SQLAlchemy — The Database Toolkit for Python — Dokumentasi resmi SQLAlchemy sebagai pembanding.
- Using EXPLAIN — PostgreSQL Documentation — Menilai SQL yang dihasilkan ORM melalui rencananya.
- Queries — PostgreSQL Documentation — Fondasi SQL yang menjadi alat pembandingnya.